ColorStateList.java revision e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1
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();
27445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            final int baseColor = a.getColor(R.styleable.ColorStateListItem_color, 0);
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
299cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            // Apply alpha modulation.
30045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            final int color = modulateColorAlpha(baseColor, alphaMod);
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (listSize == 0 || stateSpec.length == 0) {
30245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                defaultColor = color;
30345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            }
30445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
30545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            if (themeAttrs != null) {
30645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                hasUnresolvedAttrs = true;
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
308cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette
309776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski            colorList = GrowingArrayUtils.append(colorList, listSize, color);
31045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            themeAttrsList = GrowingArrayUtils.append(themeAttrsList, listSize, themeAttrs);
311776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski            stateSpecList = GrowingArrayUtils.append(stateSpecList, listSize, stateSpec);
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            listSize++;
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
31545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        mChangingConfigurations = changingConfigurations;
31645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        mDefaultColor = defaultColor;
31745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
31845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (hasUnresolvedAttrs) {
31945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            mThemeAttrs = new int[listSize][];
32045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            System.arraycopy(themeAttrsList, 0, mThemeAttrs, 0, listSize);
32145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        } else {
32245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            mThemeAttrs = null;
32345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
32445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mColors = new int[listSize];
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStateSpecs = new int[listSize][];
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        System.arraycopy(colorList, 0, mColors, 0, listSize);
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        System.arraycopy(stateSpecList, 0, mStateSpecs, 0, listSize);
32945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
33045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        onColorsChanged();
33145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    }
33245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
33345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    /**
33445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * Returns whether a theme can be applied to this color state list, which
33545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * usually indicates that the color state list has unresolved theme
33645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * attributes.
33745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *
33845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @return whether a theme can be applied to this color state list
339e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @hide only for resource preloading
34045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     */
34145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    public boolean canApplyTheme() {
34245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        return mThemeAttrs != null;
34345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    }
34445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
34545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    /**
34645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * Applies a theme to this color state list.
347e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * <p>
348e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * <strong>Note:</strong> Applying a theme may affect the changing
349e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * configuration parameters of this color state list. After calling this
350e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * method, any dependent configurations must be updated by obtaining the
351e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * new configuration mask from {@link #getChangingConfigurations()}.
35245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *
35345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @param t the theme to apply
35445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     */
355e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    private void applyTheme(Theme t) {
35645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (mThemeAttrs == null) {
35745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return;
35845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
35945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
36045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        boolean hasUnresolvedAttrs = false;
36145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
36245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final int[][] themeAttrsList = mThemeAttrs;
36345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final int N = themeAttrsList.length;
36445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        for (int i = 0; i < N; i++) {
36545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            if (themeAttrsList[i] != null) {
36645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                final TypedArray a = t.resolveAttributes(themeAttrsList[i],
36745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                        R.styleable.ColorStateListItem);
36845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                final int baseColor = a.getColor(
36945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                        R.styleable.ColorStateListItem_color, mColors[i]);
37045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                final float alphaMod = a.getFloat(
37145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                        R.styleable.ColorStateListItem_alpha, 1.0f);
37245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
37345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                mColors[i] = modulateColorAlpha(baseColor, alphaMod);
37445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                mChangingConfigurations |= a.getChangingConfigurations();
37545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
37645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                themeAttrsList[i] = a.extractThemeAttrs(themeAttrsList[i]);
37745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                if (themeAttrsList[i] != null) {
37845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    hasUnresolvedAttrs = true;
37945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                }
38045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
38145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                a.recycle();
38245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            }
38345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
38445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
38545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (!hasUnresolvedAttrs) {
38645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            mThemeAttrs = null;
38745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
38845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
38945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        onColorsChanged();
39045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    }
39145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
392e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    /**
393e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * Returns an appropriately themed color state list.
394e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     *
395e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @param t the theme to apply
396e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @return a copy of the color state list with the theme applied, or the
397e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     *         color state list itself if there were no unresolved theme
398e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     *         attributes
399e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @hide only for resource preloading
400e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     */
401e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    public ColorStateList obtainForTheme(Theme t) {
402e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        if (t == null || !canApplyTheme()) {
403e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            return this;
404e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        }
405e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette
406e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        final ColorStateList clone = new ColorStateList(this);
407e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        clone.applyTheme(t);
408e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        return clone;
409e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    }
410e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette
411e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    /**
412e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * Returns a mask of the configuration parameters for which this color
413e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * state list may change, requiring that it be re-created.
414e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     *
415e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @return a mask of the changing configuration parameters, as defined by
416e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     *         {@link android.content.pm.ActivityInfo}
417e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     *
418e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @see android.content.pm.ActivityInfo
419e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     */
420e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    public int getChangingConfigurations() {
421e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        return mChangingConfigurations;
422e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    }
423e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette
42445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private int modulateColorAlpha(int baseColor, float alphaMod) {
42545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (alphaMod == 1.0f) {
42645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return baseColor;
42745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
42845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
42945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final int baseAlpha = Color.alpha(baseColor);
43045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final int alpha = MathUtils.constrain((int) (baseAlpha * alphaMod + 0.5f), 0, 255);
431e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        return (baseColor & 0xFFFFFF) | (alpha << 24);
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4343b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette    /**
4353b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * Indicates whether this color state list contains more than one state spec
4363b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * and will change color based on state.
4373b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     *
4383b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * @return True if this color state list changes color based on state, false
4393b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     *         otherwise.
4403b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * @see #getColorForState(int[], int)
4413b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     */
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isStateful() {
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStateSpecs.length > 1;
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
445a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
4463b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette    /**
4473b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * Indicates whether this color state list is opaque, which means that every
4483b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * color returned from {@link #getColorForState(int[], int)} has an alpha
4493b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * value of 255.
4503b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     *
4513b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * @return True if this color state list is opaque.
4523b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     */
453a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    public boolean isOpaque() {
45445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        return mIsOpaque;
455a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    }
456a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
45845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * Return the color associated with the given set of
45945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * {@link android.view.View} states.
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param stateSet an array of {@link android.view.View} states
46245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * @param defaultColor the color to return if there's no matching state
46345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *                     spec in this {@link ColorStateList} that matches the
46445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *                     stateSet.
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the color associated with that set of states in this {@link ColorStateList}.
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
46845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    public int getColorForState(@Nullable int[] stateSet, int defaultColor) {
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int setLength = mStateSpecs.length;
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < setLength; i++) {
47145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            final int[] stateSpec = mStateSpecs[i];
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (StateSet.stateSetMatches(stateSpec, stateSet)) {
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mColors[i];
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return defaultColor;
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the default color in this {@link ColorStateList}.
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the default color in this {@link ColorStateList}.
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
48480756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getDefaultColor() {
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mDefaultColor;
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
48939fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    /**
49045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * Return the states in this {@link ColorStateList}. The returned array
49145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * should not be modified.
49245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *
49339fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     * @return the states in this {@link ColorStateList}
49439fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     * @hide
49539fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     */
49639fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    public int[][] getStates() {
49739fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi        return mStateSpecs;
49839fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    }
49939fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi
50039fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    /**
50145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * Return the colors in this {@link ColorStateList}. The returned array
50245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * should not be modified.
50345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     *
50439fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     * @return the colors in this {@link ColorStateList}
50539fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     * @hide
50639fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     */
50739fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    public int[] getColors() {
50839fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi        return mColors;
50939fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    }
51039fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi
5110ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    /**
5120ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * Returns whether the specified state is referenced in any of the state
5130ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * specs contained within this ColorStateList.
5140ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * <p>
5150ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * Any reference, either positive or negative {ex. ~R.attr.state_enabled},
5160ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * will cause this method to return {@code true}. Wildcards are not counted
5170ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * as references.
5180ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     *
5190ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param state the state to search for
5200ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @return {@code true} if the state if referenced, {@code false} otherwise
5210ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @hide Use only as directed. For internal use only.
5220ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     */
5230ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public boolean hasState(int state) {
5240ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int[][] stateSpecs = mStateSpecs;
5250ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int specCount = stateSpecs.length;
5260ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        for (int specIndex = 0; specIndex < specCount; specIndex++) {
5270ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            final int[] states = stateSpecs[specIndex];
5280ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            final int stateCount = states.length;
5290ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            for (int stateIndex = 0; stateIndex < stateCount; stateIndex++) {
5300ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                if (states[stateIndex] == state || states[stateIndex] == ~state) {
5310ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                    return true;
5320ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                }
5330ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            }
5340ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
5350ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        return false;
5360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
5370ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
538cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette    @Override
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String toString() {
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return "ColorStateList{" +
54145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette               "mThemeAttrs=" + Arrays.deepToString(mThemeAttrs) +
54245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette               "mChangingConfigurations=" + mChangingConfigurations +
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               "mStateSpecs=" + Arrays.deepToString(mStateSpecs) +
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               "mColors=" + Arrays.toString(mColors) +
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               "mDefaultColor=" + mDefaultColor + '}';
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
54845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    /**
54945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     * Updates the default color and opacity.
55045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     */
55145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private void onColorsChanged() {
55245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        int defaultColor = DEFAULT_COLOR;
55345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        boolean isOpaque = true;
55445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
55545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final int[][] states = mStateSpecs;
55645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final int[] colors = mColors;
55745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final int N = states.length;
55845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (N > 0) {
55945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            defaultColor = colors[0];
56045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
56145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            for (int i = N - 1; i > 0; i--) {
56245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                if (states[i].length == 0) {
56345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    defaultColor = colors[i];
56445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    break;
56545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                }
56645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            }
56745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
56845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            for (int i = 0; i < N; i++) {
56945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                if (Color.alpha(colors[i]) != 0xFF) {
57045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    isOpaque = false;
57145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    break;
57245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                }
57345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            }
57445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
57545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
57645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        mDefaultColor = defaultColor;
57745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        mIsOpaque = isOpaque;
57845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    }
57945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
58045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    /**
581e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @return a factory that can create new instances of this ColorStateList
582e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @hide only for resource preloading
58345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette     */
584e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    public ConstantState<ColorStateList> getConstantState() {
585e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        if (mFactory != null) {
586e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mFactory = new ColorStateListFactory(this);
587e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        }
588e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        return mFactory;
58945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    }
59045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
591e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette    private static class ColorStateListFactory extends ConstantState<ColorStateList> {
592e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        private final ColorStateList mSrc;
59345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
59445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        public ColorStateListFactory(ColorStateList src) {
59545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            mSrc = src;
59645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
59745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
59845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        @Override
59945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        public int getChangingConfigurations() {
60045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return mSrc.mChangingConfigurations;
60145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
60245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
60345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        @Override
60445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        public ColorStateList newInstance() {
60545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return mSrc;
60645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
60745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
60845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        @Override
60945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        public ColorStateList newInstance(Resources res, Theme theme) {
610e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            return mSrc.obtainForTheme(theme);
61145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
61245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    }
61345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
614cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette    @Override
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int describeContents() {
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
619cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette    @Override
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void writeToParcel(Parcel dest, int flags) {
62145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (canApplyTheme()) {
62245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            Log.w(TAG, "Wrote partially-resolved ColorStateList to parcel!");
62345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mStateSpecs.length;
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dest.writeInt(N);
626cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette        for (int i = 0; i < N; i++) {
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dest.writeIntArray(mStateSpecs[i]);
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dest.writeIntArray(mColors);
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final Parcelable.Creator<ColorStateList> CREATOR =
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            new Parcelable.Creator<ColorStateList>() {
634cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette        @Override
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ColorStateList[] newArray(int size) {
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new ColorStateList[size];
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
639cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette        @Override
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ColorStateList createFromParcel(Parcel source) {
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = source.readInt();
642cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            final int[][] stateSpecs = new int[N][];
643cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            for (int i = 0; i < N; i++) {
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                stateSpecs[i] = source.createIntArray();
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
646cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            final int[] colors = source.createIntArray();
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new ColorStateList(stateSpecs, colors);
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
651