ColorStateList.java revision 3b5c4272db3e089c4a06d2db2ddf2aee5ebb6281
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
19a211dd28b93473c452d68432c602d5209b01c178Alan Viveretteimport android.graphics.Color;
20cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.util.ArrayUtils;
22776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinskiimport com.android.internal.util.GrowingArrayUtils;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParser;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
28cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viveretteimport android.util.MathUtils;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.SparseArray;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.StateSet;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Xml;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcel;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcelable;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.ref.WeakReference;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Arrays;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Lets you map {@link android.view.View} state sets to colors.
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.res.ColorStateList}s are created from XML resource files defined in the
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "color" subdirectory directory of an application's resource directory.  The XML file contains
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a single "selector" element with a number of "item" elements inside.  For example:
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre>
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * &lt;selector xmlns:android="http://schemas.android.com/apk/res/android"&gt;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   &lt;item android:state_focused="true" android:color="@color/testcolor1"/&gt;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   &lt;item android:state_pressed="true" android:state_enabled="false" android:color="@color/testcolor2" /&gt;
5179dc8ccddd846816d4e0e55405ad0dbefa5b0ff6Romain Guy *   &lt;item android:state_enabled="false" android:color="@color/testcolor3" /&gt;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   &lt;item android:color="@color/testcolor5"/&gt;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * &lt;/selector&gt;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre>
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This defines a set of state spec / color pairs where each state spec specifies a set of
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * states that a view must either be in or not be in and the color specifies the color associated
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * with that spec.  The list of state specs will be processed in order of the items in the XML file.
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An item with no state spec is considered to match any set of states and is generally useful as
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in the list then any subsequent items will end up being ignored.
628dd87ad9440bc63bc312b06f292adcd2642b1c41Scott Main * <p>For more information, see the guide to <a
638dd87ad9440bc63bc312b06f292adcd2642b1c41Scott Main * href="{@docRoot}guide/topics/resources/color-list-resource.html">Color State
648dd87ad9440bc63bc312b06f292adcd2642b1c41Scott Main * List Resource</a>.</p>
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ColorStateList implements Parcelable {
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int[][] mStateSpecs; // must be parallel to mColors
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int[] mColors;      // must be parallel to mStateSpecs
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mDefaultColor = 0xffff0000;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[][] EMPTY = new int[][] { new int[0] };
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final SparseArray<WeakReference<ColorStateList>> sCache =
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            new SparseArray<WeakReference<ColorStateList>>();
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ColorStateList() { }
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Creates a ColorStateList that returns the specified mapping from
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * states to colors.
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ColorStateList(int[][] states, int[] colors) {
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStateSpecs = states;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mColors = colors;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (states.length > 0) {
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDefaultColor = colors[0];
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < states.length; i++) {
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (states[i].length == 0) {
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mDefaultColor = colors[i];
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Creates or retrieves a ColorStateList that always returns a single color.
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static ColorStateList valueOf(int color) {
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO: should we collect these eventually?
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (sCache) {
1023b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette            final WeakReference<ColorStateList> ref = sCache.get(color);
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1043b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette            ColorStateList csl = ref != null ? ref.get() : null;
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (csl != null) {
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return csl;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            csl = new ColorStateList(EMPTY, new int[] { color });
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sCache.put(color, new WeakReference<ColorStateList>(csl));
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return csl;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a ColorStateList from an XML document, given a set of {@link Resources}.
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static ColorStateList createFromXml(Resources r, XmlPullParser parser)
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws XmlPullParserException, IOException {
1203b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette        final AttributeSet attrs = Xml.asAttributeSet(parser);
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while ((type=parser.next()) != XmlPullParser.START_TAG
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                   && type != XmlPullParser.END_DOCUMENT) {
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (type != XmlPullParser.START_TAG) {
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new XmlPullParserException("No start tag found");
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return createFromXmlInner(r, parser, attrs);
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1343b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette    /**
1353b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * Create from inside an XML document. Called on a parser positioned at a
1363b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * tag in an XML document, tries to create a ColorStateList from that tag.
1373b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     *
1383b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * @throws XmlPullParserException if the current tag is not &lt;selector>
1393b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * @return A color state list for the current tag.
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static ColorStateList createFromXmlInner(Resources r, XmlPullParser parser,
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            AttributeSet attrs) throws XmlPullParserException, IOException {
1433b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette        final ColorStateList colorStateList;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String name = parser.getName();
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (name.equals("selector")) {
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            colorStateList = new ColorStateList();
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new XmlPullParserException(
1493b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette                    parser.getPositionDescription() + ": invalid drawable tag " + name);
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        colorStateList.inflate(r, parser, attrs);
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return colorStateList;
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Creates a new ColorStateList that has the same states and
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * colors as this one but where each color has the specified alpha value
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (0-255).
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ColorStateList withAlpha(int alpha) {
1623b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette        final int[] colors = new int[mColors.length];
1633b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette        final int len = colors.length;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < len; i++) {
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            colors[i] = (mColors[i] & 0xFFFFFF) | (alpha << 24);
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new ColorStateList(mStateSpecs, colors);
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Fill in this object based on the contents of an XML "selector" element.
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
175cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            throws XmlPullParserException, IOException {
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int innerDepth = parser.getDepth()+1;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int depth;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
181776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski        int[][] stateSpecList = ArrayUtils.newUnpaddedArray(int[].class, 20);
182776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski        int[] colorList = new int[stateSpecList.length];
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int listSize = 0;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               && ((depth=parser.getDepth()) >= innerDepth
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                   || type != XmlPullParser.END_TAG)) {
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (type != XmlPullParser.START_TAG) {
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (depth > innerDepth || !parser.getName().equals("item")) {
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
196cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            int alphaRes = 0;
197cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            float alpha = 1.0f;
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int colorRes = 0;
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int color = 0xffff0000;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean haveColor = false;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int i;
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int j = 0;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int numAttrs = attrs.getAttributeCount();
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int[] stateSpec = new int[numAttrs];
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (i = 0; i < numAttrs; i++) {
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int stateResId = attrs.getAttributeNameResource(i);
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (stateResId == 0) break;
209cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette                if (stateResId == com.android.internal.R.attr.alpha) {
210cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette                    alphaRes = attrs.getAttributeResourceValue(i, 0);
211cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette                    if (alphaRes == 0) {
212cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette                        alpha = attrs.getAttributeFloatValue(i, 1.0f);
213cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette                    }
214cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette                } else if (stateResId == com.android.internal.R.attr.color) {
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    colorRes = attrs.getAttributeResourceValue(i, 0);
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (colorRes == 0) {
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        color = attrs.getAttributeIntValue(i, color);
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        haveColor = true;
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    stateSpec[j++] = attrs.getAttributeBooleanValue(i, false)
222cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette                            ? stateResId : -stateResId;
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stateSpec = StateSet.trimStateSet(stateSpec, j);
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (colorRes != 0) {
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                color = r.getColor(colorRes);
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (!haveColor) {
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new XmlPullParserException(
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        parser.getPositionDescription()
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + ": <item> tag requires a 'android:color' attribute.");
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
235cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            if (alphaRes != 0) {
236cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette                alpha = r.getFraction(alphaRes, 1, 1);
237cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            }
238cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette
239cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            // Apply alpha modulation.
240cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            final int alphaMod = MathUtils.constrain((int) (Color.alpha(color) * alpha), 0, 255);
241cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            color = (color & 0xFFFFFF) | (alphaMod << 24);
242cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (listSize == 0 || stateSpec.length == 0) {
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDefaultColor = color;
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
246cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette
247776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski            colorList = GrowingArrayUtils.append(colorList, listSize, color);
248776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski            stateSpecList = GrowingArrayUtils.append(stateSpecList, listSize, stateSpec);
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            listSize++;
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mColors = new int[listSize];
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStateSpecs = new int[listSize][];
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        System.arraycopy(colorList, 0, mColors, 0, listSize);
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        System.arraycopy(stateSpecList, 0, mStateSpecs, 0, listSize);
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2583b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette    /**
2593b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * Indicates whether this color state list contains more than one state spec
2603b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * and will change color based on state.
2613b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     *
2623b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * @return True if this color state list changes color based on state, false
2633b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     *         otherwise.
2643b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * @see #getColorForState(int[], int)
2653b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     */
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isStateful() {
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStateSpecs.length > 1;
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
269a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
2703b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette    /**
2713b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * Indicates whether this color state list is opaque, which means that every
2723b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * color returned from {@link #getColorForState(int[], int)} has an alpha
2733b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * value of 255.
2743b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     *
2753b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     * @return True if this color state list is opaque.
2763b5c4272db3e089c4a06d2db2ddf2aee5ebb6281Alan Viverette     */
277a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    public boolean isOpaque() {
278a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        final int n = mColors.length;
279a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        for (int i = 0; i < n; i++) {
280a211dd28b93473c452d68432c602d5209b01c178Alan Viverette            if (Color.alpha(mColors[i]) != 0xFF) {
281a211dd28b93473c452d68432c602d5209b01c178Alan Viverette                return false;
282a211dd28b93473c452d68432c602d5209b01c178Alan Viverette            }
283a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        }
284a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        return true;
285a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    }
286a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the color associated with the given set of {@link android.view.View} states.
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param stateSet an array of {@link android.view.View} states
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param defaultColor the color to return if there's not state spec in this
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link ColorStateList} that matches the stateSet.
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the color associated with that set of states in this {@link ColorStateList}.
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getColorForState(int[] stateSet, int defaultColor) {
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int setLength = mStateSpecs.length;
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < setLength; i++) {
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int[] stateSpec = mStateSpecs[i];
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (StateSet.stateSetMatches(stateSpec, stateSet)) {
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mColors[i];
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return defaultColor;
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the default color in this {@link ColorStateList}.
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the default color in this {@link ColorStateList}.
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getDefaultColor() {
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mDefaultColor;
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
31639fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    /**
31739fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     * Return the states in this {@link ColorStateList}.
31839fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     * @return the states in this {@link ColorStateList}
31939fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     * @hide
32039fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     */
32139fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    public int[][] getStates() {
32239fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi        return mStateSpecs;
32339fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    }
32439fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi
32539fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    /**
32639fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     * Return the colors in this {@link ColorStateList}.
32739fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     * @return the colors in this {@link ColorStateList}
32839fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     * @hide
32939fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi     */
33039fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    public int[] getColors() {
33139fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi        return mColors;
33239fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi    }
33339fa59fc4907d3c8faad41bf20e1f855dbcda5e6Jorim Jaggi
334cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette    @Override
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String toString() {
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return "ColorStateList{" +
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               "mStateSpecs=" + Arrays.deepToString(mStateSpecs) +
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               "mColors=" + Arrays.toString(mColors) +
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               "mDefaultColor=" + mDefaultColor + '}';
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
342cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette    @Override
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int describeContents() {
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
347cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette    @Override
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void writeToParcel(Parcel dest, int flags) {
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mStateSpecs.length;
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dest.writeInt(N);
351cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette        for (int i = 0; i < N; i++) {
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dest.writeIntArray(mStateSpecs[i]);
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dest.writeIntArray(mColors);
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final Parcelable.Creator<ColorStateList> CREATOR =
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            new Parcelable.Creator<ColorStateList>() {
359cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette        @Override
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ColorStateList[] newArray(int size) {
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new ColorStateList[size];
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
364cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette        @Override
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ColorStateList createFromParcel(Parcel source) {
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = source.readInt();
367cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            final int[][] stateSpecs = new int[N][];
368cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            for (int i = 0; i < N; i++) {
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                stateSpecs[i] = source.createIntArray();
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
371cc3f33853b8ea5ce56ebfb14fdc3c000a45e0d78Alan Viverette            final int[] colors = source.createIntArray();
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new ColorStateList(stateSpecs, colors);
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
376