ContextThemeWrapper.java revision cc2a1d48a0e4134823c940291f5db6fd9f2ae9b3
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.view;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19417ee5ba89f7e0fe5efd34fce74bf1ee5923d976Tor Norbyeimport android.annotation.StyleRes;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContextWrapper;
22756220bd1912535840388a6743830d2e59ad4964Dianne Hackbornimport android.content.res.Configuration;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A ContextWrapper that allows you to modify the theme from what is in the
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * wrapped context.
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ContextThemeWrapper extends ContextWrapper {
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mThemeResource;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Resources.Theme mTheme;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private LayoutInflater mInflater;
33756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn    private Configuration mOverrideConfiguration;
34756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn    private Resources mResources;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ContextThemeWrapper() {
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(null);
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
39b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette
40417ee5ba89f7e0fe5efd34fce74bf1ee5923d976Tor Norbye    public ContextThemeWrapper(Context base, @StyleRes int themeResId) {
41b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette        super(base);
42b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette        mThemeResource = themeResId;
43b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette    }
44b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette
45b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette    public ContextThemeWrapper(Context base, Resources.Theme theme) {
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(base);
47b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette        mTheme = theme;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
50b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette    @Override
51b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette    protected void attachBaseContext(Context newBase) {
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.attachBaseContext(newBase);
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
54756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn
55756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn    /**
56756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn     * Call to set an "override configuration" on this context -- this is
57756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn     * a configuration that replies one or more values of the standard
58756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn     * configuration that is applied to the context.  See
59756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn     * {@link Context#createConfigurationContext(Configuration)} for more
60756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn     * information.
61756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn     *
62756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn     * <p>This method can only be called once, and must be called before any
63756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn     * calls to {@link #getResources()} are made.
64756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn     */
65756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn    public void applyOverrideConfiguration(Configuration overrideConfiguration) {
66756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn        if (mResources != null) {
67756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn            throw new IllegalStateException("getResources() has already been called");
68756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn        }
69756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn        if (mOverrideConfiguration != null) {
70756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn            throw new IllegalStateException("Override configuration has already been set");
71756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn        }
72756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn        mOverrideConfiguration = new Configuration(overrideConfiguration);
73756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn    }
74756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn
75756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn    @Override
76756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn    public Resources getResources() {
77756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn        if (mResources != null) {
78756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn            return mResources;
79756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn        }
80756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn        if (mOverrideConfiguration == null) {
81756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn            mResources = super.getResources();
82756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn            return mResources;
83756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn        } else {
84756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn            Context resc = createConfigurationContext(mOverrideConfiguration);
85756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn            mResources = resc.getResources();
86756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn            return mResources;
87756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn        }
88756220bd1912535840388a6743830d2e59ad4964Dianne Hackborn    }
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
90cc2a1d48a0e4134823c940291f5db6fd9f2ae9b3Alan Viverette    @Override
91cc2a1d48a0e4134823c940291f5db6fd9f2ae9b3Alan Viverette    public void setTheme(int resid) {
92cc2a1d48a0e4134823c940291f5db6fd9f2ae9b3Alan Viverette        if (mThemeResource != resid) {
93cc2a1d48a0e4134823c940291f5db6fd9f2ae9b3Alan Viverette            mThemeResource = resid;
94cc2a1d48a0e4134823c940291f5db6fd9f2ae9b3Alan Viverette            initializeTheme();
95cc2a1d48a0e4134823c940291f5db6fd9f2ae9b3Alan Viverette        }
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
98247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    /** @hide */
99247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    @Override
100247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    public int getThemeResId() {
101247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        return mThemeResource;
102247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    }
103247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override public Resources.Theme getTheme() {
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mTheme != null) {
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mTheme;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1095effd7e89f83824ac8982a6cbcebbf5cc331e436Alan Viverette        mThemeResource = Resources.selectDefaultTheme(mThemeResource,
110d922ae01ca99a2b6d39a9393f86776a1d10ebd14Dianne Hackborn                getApplicationInfo().targetSdkVersion);
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initializeTheme();
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mTheme;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override public Object getSystemService(String name) {
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LAYOUT_INFLATER_SERVICE.equals(name)) {
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mInflater == null) {
119ebb9f3a1a3cb405dac7f98815b37c198c65739cdFabrice Di Meglio                mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mInflater;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
123ebb9f3a1a3cb405dac7f98815b37c198c65739cdFabrice Di Meglio        return getBaseContext().getSystemService(name);
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called by {@link #setTheme} and {@link #getTheme} to apply a theme
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * resource to the current Theme object.  Can override to change the
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * default (simple) behavior.  This method will not be called in multiple
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * threads simultaneously.
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param theme The Theme object being modified.
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param resid The theme style resource being applied to <var>theme</var>.
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param first Set to true if this is the first time a style is being
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *              applied to <var>theme</var>.
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        theme.applyStyle(resid, true);
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void initializeTheme() {
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean first = mTheme == null;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (first) {
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTheme = getResources().newTheme();
145ebb9f3a1a3cb405dac7f98815b37c198c65739cdFabrice Di Meglio            Resources.Theme theme = getBaseContext().getTheme();
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (theme != null) {
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTheme.setTo(theme);
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onApplyThemeResource(mTheme, mThemeResource, first);
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
154