ColorStateList.java revision 4feb3260152b2ddbd4a96c43c09cd1ed3cf2d3fb
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 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.content.res;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1980756e38882720860db52f1fcc21fa1505a02abfTor Norbyeimport android.annotation.ColorInt;
2045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viveretteimport android.annotation.NonNull;
2145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viveretteimport android.annotation.Nullable;
2245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viveretteimport android.content.res.Resources.Theme;
23a211dd28b93473c452d68432c602d5209b01c178Alan Viveretteimport android.graphics.Color;
24cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette
2545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viveretteimport com.android.internal.R;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.util.ArrayUtils;
27776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinskiimport com.android.internal.util.GrowingArrayUtils;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParser;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
3345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viveretteimport android.util.Log;
34cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viveretteimport android.util.MathUtils;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.SparseArray;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.StateSet;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Xml;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcel;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcelable;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.ref.WeakReference;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Arrays;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Lets you map {@link android.view.View} state sets to colors.
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.res.ColorStateList}s are created from XML resource files defined in the
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "color" subdirectory directory of an application's resource directory.  The XML file contains
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a single "selector" element with a number of "item" elements inside.  For example:
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre>
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * &lt;selector xmlns:android="http://schemas.android.com/apk/res/android"&gt;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   &lt;item android:state_focused="true" android:color="@color/testcolor1"/&gt;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   &lt;item android:state_pressed="true" android:state_enabled="false" android:color="@color/testcolor2" /&gt;
5779dc8ccddd846816d4e0e55405ad0dbefa5b0ff6Romain Guy *   &lt;item android:state_enabled="false" android:color="@color/testcolor3" /&gt;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   &lt;item android:color="@color/testcolor5"/&gt;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * &lt;/selector&gt;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre>
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This defines a set of state spec / color pairs where each state spec specifies a set of
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * states that a view must either be in or not be in and the color specifies the color associated
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * with that spec.  The list of state specs will be processed in order of the items in the XML file.
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An item with no state spec is considered to match any set of states and is generally useful as
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a final item to be used as a default.  Note that if you have such an item before any other items
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in the list then any subsequent items will end up being ignored.
688dd87ad9440bc63bc312b06f292adcd2642b1c41Scott Main * <p>For more information, see the guide to <a
698dd87ad9440bc63bc312b06f292adcd2642b1c41Scott Main * href="{@docRoot}guide/topics/resources/color-list-resource.html">Color State
708dd87ad9440bc63bc312b06f292adcd2642b1c41Scott Main * List Resource</a>.</p>
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ColorStateList implements Parcelable {
7345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private static final String TAG = "ColorStateList";
74e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette
7545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private static final int DEFAULT_COLOR = Color.RED;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[][] EMPTY = new int[][] { new int[0] };
77e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette
78e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    /** Thread-safe cache of single-color ColorStateLists. */
79e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    private static final SparseArray<WeakReference<ColorStateList>> sCache = new SparseArray<>();
80e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette
81e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    /** Lazily-created factory for this color state list. */
82e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    private ColorStateListFactory mFactory;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private int[][] mThemeAttrs;
8545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private int mChangingConfigurations;
8645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
8745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private int[][] mStateSpecs;
8845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private int[] mColors;
8945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private int mDefaultColor;
9045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private boolean mIsOpaque;
9145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
9245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private ColorStateList() {
9345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        // Not publicly instantiable.
9445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    }
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Creates a ColorStateList that returns the specified mapping from
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * states to colors.
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10080756e38882720860db52f1fcc21fa1505a02abfTor Norbye    public ColorStateList(int[][] states, @ColorInt int[] colors) {
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStateSpecs = states;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mColors = colors;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        onColorsChanged();
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @return A ColorStateList containing a single color.
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    @NonNull
11180756e38882720860db52f1fcc21fa1505a02abfTor Norbye    public static ColorStateList valueOf(@ColorInt int color) {
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (sCache) {
11345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            final int index = sCache.indexOfKey(color);
11445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            if (index >= 0) {
11545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                final ColorStateList cached = sCache.valueAt(index).get();
11645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                if (cached != null) {
11745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    return cached;
11845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                }
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                // Prune missing entry.
12145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                sCache.removeAt(index);
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            // Prune the cache before adding new items.
12545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            final int N = sCache.size();
12645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            for (int i = N - 1; i >= 0; i--) {
12745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                if (sCache.valueAt(i).get() == null) {
12845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    sCache.removeAt(i);
12945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                }
13045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            }
13145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
13245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            final ColorStateList csl = new ColorStateList(EMPTY, new int[] { color });
133e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            sCache.put(color, new WeakReference<>(csl));
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return csl;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * Creates a ColorStateList with the same properties as another
14045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * ColorStateList.
14145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * <p>
14245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * The properties of the new ColorStateList can be modified without
14345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * affecting the source ColorStateList.
14445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *
14545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @param orig the source color state list
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private ColorStateList(ColorStateList orig) {
14845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (orig != null) {
149e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mChangingConfigurations = orig.mChangingConfigurations;
15045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            mStateSpecs = orig.mStateSpecs;
15145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            mDefaultColor = orig.mDefaultColor;
15245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            mIsOpaque = orig.mIsOpaque;
15345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
154e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            // Deep copy, these may change due to applyTheme().
155e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mThemeAttrs = orig.mThemeAttrs.clone();
15645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            mColors = orig.mColors.clone();
15745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
15845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    }
15945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
16045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    /**
16145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * Creates a ColorStateList from an XML document.
16245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *
16345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @param r Resources against which the ColorStateList should be inflated.
16445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @param parser Parser for the XML document defining the ColorStateList.
16545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @return A new color state list.
16645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *
16745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @deprecated Use #createFromXml(Resources, XmlPullParser parser, Theme)
16845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     */
16945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    @NonNull
17045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    @Deprecated
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static ColorStateList createFromXml(Resources r, XmlPullParser parser)
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws XmlPullParserException, IOException {
17345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        return createFromXml(r, parser, null);
17445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    }
17545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
17645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    /**
17745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * Creates a ColorStateList from an XML document using given a set of
17845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * {@link Resources} and a {@link Theme}.
17945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *
18045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @param r Resources against which the ColorStateList should be inflated.
18145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @param parser Parser for the XML document defining the ColorStateList.
18245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @param theme Optional theme to apply to the color state list, may be
18345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *              {@code null}.
18445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @return A new color state list.
18545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     */
18645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    @NonNull
18745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    public static ColorStateList createFromXml(@NonNull Resources r, @NonNull XmlPullParser parser,
18845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            @Nullable Theme theme) throws XmlPullParserException, IOException {
1893b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette        final AttributeSet attrs = Xml.asAttributeSet(parser);
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
19245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        while ((type = parser.next()) != XmlPullParser.START_TAG
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                   && type != XmlPullParser.END_DOCUMENT) {
19445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            // Seek parser to start tag.
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (type != XmlPullParser.START_TAG) {
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new XmlPullParserException("No start tag found");
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        return createFromXmlInner(r, parser, attrs, theme);
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2043b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette    /**
2053b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * Create from inside an XML document. Called on a parser positioned at a
2063b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * tag in an XML document, tries to create a ColorStateList from that tag.
2073b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     *
2083b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * @throws XmlPullParserException if the current tag is not &lt;selector>
20945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @return A new color state list for the current tag.
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
21145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    @NonNull
21245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private static ColorStateList createFromXmlInner(@NonNull Resources r,
21345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme)
21445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            throws XmlPullParserException, IOException {
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String name = parser.getName();
21645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (!name.equals("selector")) {
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new XmlPullParserException(
21845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    parser.getPositionDescription() + ": invalid color state list tag " + name);
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final ColorStateList colorStateList = new ColorStateList();
22245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        colorStateList.inflate(r, parser, attrs, theme);
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return colorStateList;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
22745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * Creates a new ColorStateList that has the same states and colors as this
22845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * one but where each color has the specified alpha value (0-255).
22945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *
23045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @param alpha The new alpha channel value (0-255).
23145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @return A new color state list.
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
23345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    @NonNull
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ColorStateList withAlpha(int alpha) {
2353b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette        final int[] colors = new int[mColors.length];
2363b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette        final int len = colors.length;
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < len; i++) {
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            colors[i] = (mColors[i] & 0xFFFFFF) | (alpha << 24);
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new ColorStateList(mStateSpecs, colors);
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Fill in this object based on the contents of an XML "selector" element.
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
24745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
24845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            @NonNull AttributeSet attrs, @Nullable Theme theme)
249cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            throws XmlPullParserException, IOException {
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int innerDepth = parser.getDepth()+1;
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int depth;
25245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        int type;
25345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
25445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        int changingConfigurations = 0;
25545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        int defaultColor = DEFAULT_COLOR;
25645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
25745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        boolean hasUnresolvedAttrs = false;
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski        int[][] stateSpecList = ArrayUtils.newUnpaddedArray(int[].class, 20);
26045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        int[][] themeAttrsList = new int[stateSpecList.length][];
261776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski        int[] colorList = new int[stateSpecList.length];
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int listSize = 0;
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
26545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette               && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
26645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            if (type != XmlPullParser.START_TAG || depth > innerDepth
26745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || !parser.getName().equals("item")) {
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            final TypedArray a = Resources.obtainAttributes(r, theme, attrs,
27245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    R.styleable.ColorStateListItem);
27345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            final int[] themeAttrs = a.extractThemeAttrs();
274f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette            final int baseColor = a.getColor(R.styleable.ColorStateListItem_color, Color.MAGENTA);
27545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            final float alphaMod = a.getFloat(R.styleable.ColorStateListItem_alpha, 1.0f);
27645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
27745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            changingConfigurations |= a.getChangingConfigurations();
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            a.recycle();
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
28145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            // Parse all unrecognized attributes as state specifiers.
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int j = 0;
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int numAttrs = attrs.getAttributeCount();
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int[] stateSpec = new int[numAttrs];
28545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            for (int i = 0; i < numAttrs; i++) {
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int stateResId = attrs.getAttributeNameResource(i);
28745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                switch (stateResId) {
28845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    case R.attr.color:
28945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    case R.attr.alpha:
29045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                        // Recognized attribute, ignore.
29145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                        break;
29245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    default:
29345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                        stateSpec[j++] = attrs.getAttributeBooleanValue(i, false)
29445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                                ? stateResId : -stateResId;
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stateSpec = StateSet.trimStateSet(stateSpec, j);
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
299f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette            // Apply alpha modulation. If we couldn't resolve the color or
300f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette            // alpha yet, the default values leave us enough information to
301f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette            // modulate again during applyTheme().
30245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            final int color = modulateColorAlpha(baseColor, alphaMod);
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (listSize == 0 || stateSpec.length == 0) {
30445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                defaultColor = color;
30545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            }
30645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
30745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            if (themeAttrs != null) {
30845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                hasUnresolvedAttrs = true;
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
310cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette
311776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski            colorList = GrowingArrayUtils.append(colorList, listSize, color);
31245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            themeAttrsList = GrowingArrayUtils.append(themeAttrsList, listSize, themeAttrs);
313776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski            stateSpecList = GrowingArrayUtils.append(stateSpecList, listSize, stateSpec);
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            listSize++;
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
31745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        mChangingConfigurations = changingConfigurations;
31845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        mDefaultColor = defaultColor;
31945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
32045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (hasUnresolvedAttrs) {
32145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            mThemeAttrs = new int[listSize][];
32245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            System.arraycopy(themeAttrsList, 0, mThemeAttrs, 0, listSize);
32345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        } else {
32445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            mThemeAttrs = null;
32545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
32645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mColors = new int[listSize];
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStateSpecs = new int[listSize][];
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        System.arraycopy(colorList, 0, mColors, 0, listSize);
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        System.arraycopy(stateSpecList, 0, mStateSpecs, 0, listSize);
33145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
33245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        onColorsChanged();
33345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    }
33445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
33545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    /**
33645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * Returns whether a theme can be applied to this color state list, which
33745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * usually indicates that the color state list has unresolved theme
33845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * attributes.
33945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *
34045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @return whether a theme can be applied to this color state list
341e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @hide only for resource preloading
34245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     */
34345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    public boolean canApplyTheme() {
34445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        return mThemeAttrs != null;
34545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    }
34645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
34745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    /**
34845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * Applies a theme to this color state list.
349e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * <p>
350e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * <strong>Note:</strong> Applying a theme may affect the changing
351e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * configuration parameters of this color state list. After calling this
352e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * method, any dependent configurations must be updated by obtaining the
353e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * new configuration mask from {@link #getChangingConfigurations()}.
35445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *
35545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @param t the theme to apply
35645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     */
357e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    private void applyTheme(Theme t) {
35845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (mThemeAttrs == null) {
35945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return;
36045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
36145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
36245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        boolean hasUnresolvedAttrs = false;
36345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
36445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final int[][] themeAttrsList = mThemeAttrs;
36545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final int N = themeAttrsList.length;
36645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        for (int i = 0; i < N; i++) {
36745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            if (themeAttrsList[i] != null) {
36845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                final TypedArray a = t.resolveAttributes(themeAttrsList[i],
36945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                        R.styleable.ColorStateListItem);
370f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette
371f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette                final float defaultAlphaMod;
372f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette                if (themeAttrsList[i][R.styleable.ColorStateListItem_color] != 0) {
373f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette                    // If the base color hasn't been resolved yet, the current
374f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette                    // color's alpha channel is either full-opacity (if we
375f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette                    // haven't resolved the alpha modulation yet) or
376f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette                    // pre-modulated. Either is okay as a default value.
377f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette                    defaultAlphaMod = Color.alpha(mColors[i]) / 255.0f;
378f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette                } else {
379f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette                    // Otherwise, the only correct default value is 1. Even if
380f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette                    // nothing is resolved during this call, we can apply this
381f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette                    // multiple times without losing of information.
382f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette                    defaultAlphaMod = 1.0f;
383f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette                }
384f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette
38550ba321fbcecd0b050d755ff5a02eba7ab97bb00Alan Viverette                // Extract the theme attributes, if any, before attempting to
38650ba321fbcecd0b050d755ff5a02eba7ab97bb00Alan Viverette                // read from the typed array. This prevents a crash if we have
38750ba321fbcecd0b050d755ff5a02eba7ab97bb00Alan Viverette                // unresolved attrs.
38850ba321fbcecd0b050d755ff5a02eba7ab97bb00Alan Viverette                themeAttrsList[i] = a.extractThemeAttrs(themeAttrsList[i]);
38950ba321fbcecd0b050d755ff5a02eba7ab97bb00Alan Viverette                if (themeAttrsList[i] != null) {
39050ba321fbcecd0b050d755ff5a02eba7ab97bb00Alan Viverette                    hasUnresolvedAttrs = true;
39150ba321fbcecd0b050d755ff5a02eba7ab97bb00Alan Viverette                }
39250ba321fbcecd0b050d755ff5a02eba7ab97bb00Alan Viverette
39345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                final int baseColor = a.getColor(
39445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                        R.styleable.ColorStateListItem_color, mColors[i]);
39545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                final float alphaMod = a.getFloat(
396f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette                        R.styleable.ColorStateListItem_alpha, defaultAlphaMod);
39745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                mColors[i] = modulateColorAlpha(baseColor, alphaMod);
398f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette
399f601440e21f352f5e59dd27e6709c7137cd90090Alan Viverette                // Account for any configuration changes.
40045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                mChangingConfigurations |= a.getChangingConfigurations();
40145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
40245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                a.recycle();
40345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            }
40445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
40545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
40645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (!hasUnresolvedAttrs) {
40745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            mThemeAttrs = null;
40845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
40945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
41045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        onColorsChanged();
41145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    }
41245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
413e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    /**
414e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * Returns an appropriately themed color state list.
415e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     *
416e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @param t the theme to apply
417e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @return a copy of the color state list with the theme applied, or the
418e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     *         color state list itself if there were no unresolved theme
419e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     *         attributes
420e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @hide only for resource preloading
421e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     */
422e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    public ColorStateList obtainForTheme(Theme t) {
423e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        if (t == null || !canApplyTheme()) {
424e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            return this;
425e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        }
426e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette
427e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        final ColorStateList clone = new ColorStateList(this);
428e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        clone.applyTheme(t);
429e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        return clone;
430e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    }
431e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette
432e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    /**
433e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * Returns a mask of the configuration parameters for which this color
434e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * state list may change, requiring that it be re-created.
435e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     *
436e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @return a mask of the changing configuration parameters, as defined by
437e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     *         {@link android.content.pm.ActivityInfo}
438e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     *
439e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @see android.content.pm.ActivityInfo
440e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     */
441e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    public int getChangingConfigurations() {
442e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        return mChangingConfigurations;
443e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    }
444e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette
44545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private int modulateColorAlpha(int baseColor, float alphaMod) {
44645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (alphaMod == 1.0f) {
44745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return baseColor;
44845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
44945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
45045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final int baseAlpha = Color.alpha(baseColor);
45145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final int alpha = MathUtils.constrain((int) (baseAlpha * alphaMod + 0.5f), 0, 255);
452e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        return (baseColor & 0xFFFFFF) | (alpha << 24);
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4553b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette    /**
4563b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * Indicates whether this color state list contains more than one state spec
4573b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * and will change color based on state.
4583b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     *
4593b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * @return True if this color state list changes color based on state, false
4603b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     *         otherwise.
4613b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * @see #getColorForState(int[], int)
4623b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     */
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isStateful() {
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStateSpecs.length > 1;
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
466a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
4673b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette    /**
4683b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * Indicates whether this color state list is opaque, which means that every
4693b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * color returned from {@link #getColorForState(int[], int)} has an alpha
4703b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * value of 255.
4713b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     *
4723b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * @return True if this color state list is opaque.
4733b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     */
474a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    public boolean isOpaque() {
47545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        return mIsOpaque;
476a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    }
477a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
47945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * Return the color associated with the given set of
48045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * {@link android.view.View} states.
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param stateSet an array of {@link android.view.View} states
48345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @param defaultColor the color to return if there's no matching state
48445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *                     spec in this {@link ColorStateList} that matches the
48545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *                     stateSet.
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the color associated with that set of states in this {@link ColorStateList}.
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
48945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    public int getColorForState(@Nullable int[] stateSet, int defaultColor) {
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int setLength = mStateSpecs.length;
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < setLength; i++) {
49245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            final int[] stateSpec = mStateSpecs[i];
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (StateSet.stateSetMatches(stateSpec, stateSet)) {
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mColors[i];
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return defaultColor;
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the default color in this {@link ColorStateList}.
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the default color in this {@link ColorStateList}.
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
50580756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getDefaultColor() {
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mDefaultColor;
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
51039fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    /**
51145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * Return the states in this {@link ColorStateList}. The returned array
51245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * should not be modified.
51345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *
51439fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     * @return the states in this {@link ColorStateList}
51539fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     * @hide
51639fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     */
51739fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    public int[][] getStates() {
51839fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi        return mStateSpecs;
51939fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    }
52039fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi
52139fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    /**
52245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * Return the colors in this {@link ColorStateList}. The returned array
52345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * should not be modified.
52445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *
52539fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     * @return the colors in this {@link ColorStateList}
52639fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     * @hide
52739fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     */
52839fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    public int[] getColors() {
52939fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi        return mColors;
53039fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    }
53139fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi
5320ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    /**
5330ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * Returns whether the specified state is referenced in any of the state
5340ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * specs contained within this ColorStateList.
5350ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * <p>
5360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * Any reference, either positive or negative {ex. ~R.attr.state_enabled},
5370ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * will cause this method to return {@code true}. Wildcards are not counted
5380ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * as references.
5390ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     *
5400ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param state the state to search for
5410ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @return {@code true} if the state if referenced, {@code false} otherwise
5420ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @hide Use only as directed. For internal use only.
5430ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     */
5440ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public boolean hasState(int state) {
5450ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int[][] stateSpecs = mStateSpecs;
5460ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int specCount = stateSpecs.length;
5470ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        for (int specIndex = 0; specIndex < specCount; specIndex++) {
5480ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            final int[] states = stateSpecs[specIndex];
5490ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            final int stateCount = states.length;
5500ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            for (int stateIndex = 0; stateIndex < stateCount; stateIndex++) {
5510ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                if (states[stateIndex] == state || states[stateIndex] == ~state) {
5520ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                    return true;
5530ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                }
5540ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            }
5550ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
5560ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        return false;
5570ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
5580ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
559cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette    @Override
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String toString() {
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return "ColorStateList{" +
56245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette               "mThemeAttrs=" + Arrays.deepToString(mThemeAttrs) +
56345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette               "mChangingConfigurations=" + mChangingConfigurations +
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               "mStateSpecs=" + Arrays.deepToString(mStateSpecs) +
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               "mColors=" + Arrays.toString(mColors) +
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               "mDefaultColor=" + mDefaultColor + '}';
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
56945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    /**
57045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * Updates the default color and opacity.
57145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     */
57245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private void onColorsChanged() {
57345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        int defaultColor = DEFAULT_COLOR;
57445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        boolean isOpaque = true;
57545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
57645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final int[][] states = mStateSpecs;
57745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final int[] colors = mColors;
57845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final int N = states.length;
57945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (N > 0) {
58045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            defaultColor = colors[0];
58145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
58245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            for (int i = N - 1; i > 0; i--) {
58345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                if (states[i].length == 0) {
58445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    defaultColor = colors[i];
58545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    break;
58645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                }
58745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            }
58845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
58945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            for (int i = 0; i < N; i++) {
59045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                if (Color.alpha(colors[i]) != 0xFF) {
59145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    isOpaque = false;
59245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    break;
59345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                }
59445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            }
59545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
59645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
59745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        mDefaultColor = defaultColor;
59845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        mIsOpaque = isOpaque;
59945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    }
60045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
60145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    /**
602e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @return a factory that can create new instances of this ColorStateList
603e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @hide only for resource preloading
60445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     */
605e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    public ConstantState<ColorStateList> getConstantState() {
6064feb3260152b2ddbd4a96c43c09cd1ed3cf2d3fbJohn Reck        if (mFactory == null) {
607e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mFactory = new ColorStateListFactory(this);
608e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        }
609e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        return mFactory;
61045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    }
61145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
612e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    private static class ColorStateListFactory extends ConstantState<ColorStateList> {
613e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        private final ColorStateList mSrc;
61445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
61545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        public ColorStateListFactory(ColorStateList src) {
61645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            mSrc = src;
61745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
61845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
61945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        @Override
62045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        public int getChangingConfigurations() {
62145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return mSrc.mChangingConfigurations;
62245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
62345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
62445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        @Override
62545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        public ColorStateList newInstance() {
62645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return mSrc;
62745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
62845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
62945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        @Override
63045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        public ColorStateList newInstance(Resources res, Theme theme) {
631e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            return mSrc.obtainForTheme(theme);
63245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
63345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    }
63445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
635cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette    @Override
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int describeContents() {
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
640cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette    @Override
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void writeToParcel(Parcel dest, int flags) {
64245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (canApplyTheme()) {
64345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            Log.w(TAG, "Wrote partially-resolved ColorStateList to parcel!");
64445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mStateSpecs.length;
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dest.writeInt(N);
647cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette        for (int i = 0; i < N; i++) {
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dest.writeIntArray(mStateSpecs[i]);
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dest.writeIntArray(mColors);
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final Parcelable.Creator<ColorStateList> CREATOR =
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            new Parcelable.Creator<ColorStateList>() {
655cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette        @Override
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ColorStateList[] newArray(int size) {
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new ColorStateList[size];
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
660cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette        @Override
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ColorStateList createFromParcel(Parcel source) {
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = source.readInt();
663cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            final int[][] stateSpecs = new int[N][];
664cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            for (int i = 0; i < N; i++) {
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                stateSpecs[i] = source.createIntArray();
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
667cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            final int[] colors = source.createIntArray();
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new ColorStateList(stateSpecs, colors);
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
672