ColorStateList.java revision d9f3fdf45bd3e3b5b02f2d21b6df6598cbaf1c70
1cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com/*
2cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * Copyright (C) 2007 The Android Open Source Project
3cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com *
4cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * Licensed under the Apache License, Version 2.0 (the "License");
5cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * you may not use this file except in compliance with the License.
6cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * You may obtain a copy of the License at
7cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com *
8cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com *      http://www.apache.org/licenses/LICENSE-2.0
9cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com *
108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * Unless required by applicable law or agreed to in writing, software
118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * distributed under the License is distributed on an "AS IS" BASIS,
128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * See the License for the specific language governing permissions and
148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * limitations under the License.
158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com */
168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.compackage android.content.res;
188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport android.graphics.Color;
208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport com.android.internal.util.ArrayUtils;
228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport com.android.internal.util.GrowingArrayUtils;
238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport org.xmlpull.v1.XmlPullParser;
258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport org.xmlpull.v1.XmlPullParserException;
268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport android.util.AttributeSet;
288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport android.util.MathUtils;
298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport android.util.SparseArray;
308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport android.util.StateSet;
318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport android.util.Xml;
328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport android.os.Parcel;
338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport android.os.Parcelable;
348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport java.io.IOException;
368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport java.lang.ref.WeakReference;
378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport java.util.Arrays;
388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com/**
408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com *
418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * Lets you map {@link android.view.View} state sets to colors.
428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com *
438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * {@link android.content.res.ColorStateList}s are created from XML resource files defined in the
448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * "color" subdirectory directory of an application's resource directory.  The XML file contains
458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * a single "selector" element with a number of "item" elements inside.  For example:
468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com *
478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * <pre>
488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * &lt;selector xmlns:android="http://schemas.android.com/apk/res/android"&gt;
498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com *   &lt;item android:state_focused="true" android:color="@color/testcolor1"/&gt;
508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com *   &lt;item android:state_pressed="true" android:state_enabled="false" android:color="@color/testcolor2" /&gt;
518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com *   &lt;item android:state_enabled="false" android:color="@color/testcolor3" /&gt;
528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com *   &lt;item android:color="@color/testcolor5"/&gt;
538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * &lt;/selector&gt;
548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * </pre>
558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com *
568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * This defines a set of state spec / color pairs where each state spec specifies a set of
578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * states that a view must either be in or not be in and the color specifies the color associated
588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * with that spec.  The list of state specs will be processed in order of the items in the XML file.
598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * An item with no state spec is considered to match any set of states and is generally useful as
608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * a final item to be used as a default.  Note that if you have such an item before any other items
618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * in the list then any subsequent items will end up being ignored.
628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * <p>For more information, see the guide to <a
638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * href="{@docRoot}guide/topics/resources/color-list-resource.html">Color State
648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * List Resource</a>.</p>
658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com */
668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.compublic class ColorStateList implements Parcelable {
678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    private int[][] mStateSpecs; // must be parallel to mColors
688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    private int[] mColors;      // must be parallel to mStateSpecs
698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    private int mDefaultColor = 0xffff0000;
708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    private static final int[][] EMPTY = new int[][] { new int[0] };
728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    private static final SparseArray<WeakReference<ColorStateList>> sCache =
738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                            new SparseArray<WeakReference<ColorStateList>>();
748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    private ColorStateList() { }
768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    /**
788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * Creates a ColorStateList that returns the specified mapping from
798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * states to colors.
808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     */
818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    public ColorStateList(int[][] states, int[] colors) {
828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        mStateSpecs = states;
838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        mColors = colors;
848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        if (states.length > 0) {
868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            mDefaultColor = colors[0];
878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            for (int i = 0; i < states.length; i++) {
898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                if (states[i].length == 0) {
908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                    mDefaultColor = colors[i];
918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                }
928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            }
938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        }
948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    }
958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    /**
978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * Creates or retrieves a ColorStateList that always returns a single color.
988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     */
998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    public static ColorStateList valueOf(int color) {
1008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        // TODO: should we collect these eventually?
1018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        synchronized (sCache) {
1028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            final WeakReference<ColorStateList> ref = sCache.get(color);
1038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            ColorStateList csl = ref != null ? ref.get() : null;
1058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            if (csl != null) {
1068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                return csl;
1078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            }
1088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            csl = new ColorStateList(EMPTY, new int[] { color });
1108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            sCache.put(color, new WeakReference<ColorStateList>(csl));
1118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            return csl;
1128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        }
1138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    }
1148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    /**
1168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * Create a ColorStateList from an XML document, given a set of {@link Resources}.
1178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     */
1188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    public static ColorStateList createFromXml(Resources r, XmlPullParser parser)
1198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            throws XmlPullParserException, IOException {
1208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        final AttributeSet attrs = Xml.asAttributeSet(parser);
1218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        int type;
1238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        while ((type=parser.next()) != XmlPullParser.START_TAG
1248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                   && type != XmlPullParser.END_DOCUMENT) {
1258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        }
1268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        if (type != XmlPullParser.START_TAG) {
1288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            throw new XmlPullParserException("No start tag found");
1298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        }
1308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        return createFromXmlInner(r, parser, attrs);
1328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    }
1338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    /**
1358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * Create from inside an XML document. Called on a parser positioned at a
1368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * tag in an XML document, tries to create a ColorStateList from that tag.
1378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     *
1388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @throws XmlPullParserException if the current tag is not &lt;selector>
1398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @return A color state list for the current tag.
1408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     */
1418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    private static ColorStateList createFromXmlInner(Resources r, XmlPullParser parser,
1428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            AttributeSet attrs) throws XmlPullParserException, IOException {
1438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        final ColorStateList colorStateList;
1448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        final String name = parser.getName();
1458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        if (name.equals("selector")) {
1468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            colorStateList = new ColorStateList();
1478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        } else {
1488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            throw new XmlPullParserException(
1498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                    parser.getPositionDescription() + ": invalid drawable tag " + name);
1508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        }
1518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        colorStateList.inflate(r, parser, attrs);
1538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        return colorStateList;
1548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    }
1558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    /**
1578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * Creates a new ColorStateList that has the same states and
1588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * colors as this one but where each color has the specified alpha value
1598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * (0-255).
1608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     */
1618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    public ColorStateList withAlpha(int alpha) {
1628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        final int[] colors = new int[mColors.length];
1638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        final int len = colors.length;
1648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        for (int i = 0; i < len; i++) {
1658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            colors[i] = (mColors[i] & 0xFFFFFF) | (alpha << 24);
1668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        }
1678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        return new ColorStateList(mStateSpecs, colors);
1698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    }
1708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    /**
1728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * Fill in this object based on the contents of an XML "selector" element.
1738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     */
1748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    private void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
1758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            throws XmlPullParserException, IOException {
1768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        int type;
1778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        final int innerDepth = parser.getDepth()+1;
1798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        int depth;
1808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        int[][] stateSpecList = ArrayUtils.newUnpaddedArray(int[].class, 20);
1828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        int[] colorList = new int[stateSpecList.length];
1838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        int listSize = 0;
1848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com               && ((depth=parser.getDepth()) >= innerDepth
1878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                   || type != XmlPullParser.END_TAG)) {
1888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            if (type != XmlPullParser.START_TAG) {
1898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                continue;
1908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            }
1918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            if (depth > innerDepth || !parser.getName().equals("item")) {
1938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                continue;
1948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            }
1958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            int alphaRes = 0;
1978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            float alpha = 1.0f;
1988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            int colorRes = 0;
1998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            int color = 0xffff0000;
2008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            boolean haveColor = false;
2018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            int i;
2038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            int j = 0;
2048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            final int numAttrs = attrs.getAttributeCount();
2058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            int[] stateSpec = new int[numAttrs];
2068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            for (i = 0; i < numAttrs; i++) {
2078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                final int stateResId = attrs.getAttributeNameResource(i);
2088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                if (stateResId == 0) break;
2098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                if (stateResId == com.android.internal.R.attr.alpha) {
2108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                    alphaRes = attrs.getAttributeResourceValue(i, 0);
2118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                    if (alphaRes == 0) {
2128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                        alpha = attrs.getAttributeFloatValue(i, 1.0f);
2138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                    }
2148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                } else if (stateResId == com.android.internal.R.attr.color) {
2158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                    colorRes = attrs.getAttributeResourceValue(i, 0);
2168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                    if (colorRes == 0) {
2178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                        color = attrs.getAttributeIntValue(i, color);
2188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                        haveColor = true;
2198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                    }
2208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                } else {
2218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                    stateSpec[j++] = attrs.getAttributeBooleanValue(i, false)
2228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                            ? stateResId : -stateResId;
2238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                }
2248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            }
2258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            stateSpec = StateSet.trimStateSet(stateSpec, j);
2268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            if (colorRes != 0) {
2288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                color = r.getColor(colorRes);
2298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            } else if (!haveColor) {
2308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                throw new XmlPullParserException(
2318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                        parser.getPositionDescription()
2328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                        + ": <item> tag requires a 'android:color' attribute.");
2338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            }
2348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            if (alphaRes != 0) {
2368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                alpha = r.getFloat(alphaRes);
2378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            }
2388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            // Apply alpha modulation.
2408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            final int alphaMod = MathUtils.constrain((int) (Color.alpha(color) * alpha), 0, 255);
2418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            color = (color & 0xFFFFFF) | (alphaMod << 24);
2428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            if (listSize == 0 || stateSpec.length == 0) {
2448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                mDefaultColor = color;
2458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            }
2468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            colorList = GrowingArrayUtils.append(colorList, listSize, color);
2488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            stateSpecList = GrowingArrayUtils.append(stateSpecList, listSize, stateSpec);
2498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            listSize++;
2508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        }
2518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        mColors = new int[listSize];
2538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        mStateSpecs = new int[listSize][];
2548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        System.arraycopy(colorList, 0, mColors, 0, listSize);
2558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        System.arraycopy(stateSpecList, 0, mStateSpecs, 0, listSize);
2568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    }
2578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    /**
2598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * Indicates whether this color state list contains more than one state spec
2608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * and will change color based on state.
2618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     *
2628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @return True if this color state list changes color based on state, false
2638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     *         otherwise.
2648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @see #getColorForState(int[], int)
2658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     */
2668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    public boolean isStateful() {
2678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        return mStateSpecs.length > 1;
2688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    }
2698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    /**
2718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * Indicates whether this color state list is opaque, which means that every
2728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * color returned from {@link #getColorForState(int[], int)} has an alpha
2738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * value of 255.
2748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     *
2758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @return True if this color state list is opaque.
2768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     */
2778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    public boolean isOpaque() {
2788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        final int n = mColors.length;
2798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        for (int i = 0; i < n; i++) {
2808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            if (Color.alpha(mColors[i]) != 0xFF) {
2818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                return false;
2828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            }
2838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        }
2848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        return true;
2858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    }
2868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    /**
2888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * Return the color associated with the given set of {@link android.view.View} states.
2898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     *
2908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @param stateSet an array of {@link android.view.View} states
2918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @param defaultColor the color to return if there's not state spec in this
2928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * {@link ColorStateList} that matches the stateSet.
2938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     *
2948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @return the color associated with that set of states in this {@link ColorStateList}.
2958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     */
2968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    public int getColorForState(int[] stateSet, int defaultColor) {
2978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        final int setLength = mStateSpecs.length;
2988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        for (int i = 0; i < setLength; i++) {
2998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            int[] stateSpec = mStateSpecs[i];
3008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            if (StateSet.stateSetMatches(stateSpec, stateSet)) {
3018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                return mColors[i];
3028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            }
3038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        }
3048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        return defaultColor;
3058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    }
3068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    /**
3088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * Return the default color in this {@link ColorStateList}.
3098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     *
3108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @return the default color in this {@link ColorStateList}.
3118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     */
3128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    public int getDefaultColor() {
3138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        return mDefaultColor;
3148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    }
3158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    /**
3178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * Return the states in this {@link ColorStateList}.
3188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @return the states in this {@link ColorStateList}
3198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @hide
3208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     */
3218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    public int[][] getStates() {
3228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        return mStateSpecs;
3238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    }
3248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    /**
3268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * Return the colors in this {@link ColorStateList}.
3278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @return the colors in this {@link ColorStateList}
3288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @hide
3298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     */
3308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    public int[] getColors() {
3318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        return mColors;
3328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    }
3338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    /**
3358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * If the color state list does not already have an entry matching the
3368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * specified state, prepends a state set and color pair to a color state
3378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * list.
3388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * <p>
3398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * This is a workaround used in TimePicker and DatePicker until we can
3408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * add support for theme attributes in ColorStateList.
3418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     *
3428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @param colorStateList the source color state list
3438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @param state the state to prepend
3448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @param color the color to use for the given state
3458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @return a new color state list, or the source color state list if there
3468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     *         was already a matching state set
3478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     *
3488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     * @hide Remove when we can support theme attributes.
3498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com     */
3508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    public static ColorStateList addFirstIfMissing(
3518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            ColorStateList colorStateList, int state, int color) {
3528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        final int[][] inputStates = colorStateList.getStates();
3538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        for (int i = 0; i < inputStates.length; i++) {
3548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            final int[] inputState = inputStates[i];
3558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            for (int j = 0; j < inputState.length; j++) {
3568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                if (inputState[j] == state) {
3578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                    return colorStateList;
3588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                }
3598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            }
3608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        }
3618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        final int[][] outputStates = new int[inputStates.length + 1][];
3638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        System.arraycopy(inputStates, 0, outputStates, 1, inputStates.length);
3648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        outputStates[0] = new int[] { state };
3658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        final int[] inputColors = colorStateList.getColors();
3678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        final int[] outputColors = new int[inputColors.length + 1];
3688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        System.arraycopy(inputColors, 0, outputColors, 1, inputColors.length);
3698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        outputColors[0] = color;
3708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        return new ColorStateList(outputStates, outputColors);
3728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    }
3738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    @Override
3758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    public String toString() {
3768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        return "ColorStateList{" +
3778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com               "mStateSpecs=" + Arrays.deepToString(mStateSpecs) +
3788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com               "mColors=" + Arrays.toString(mColors) +
3798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com               "mDefaultColor=" + mDefaultColor + '}';
3808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    }
3818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    @Override
3838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    public int describeContents() {
3848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        return 0;
3858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    }
3868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    @Override
3888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    public void writeToParcel(Parcel dest, int flags) {
3898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        final int N = mStateSpecs.length;
3908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        dest.writeInt(N);
3918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        for (int i = 0; i < N; i++) {
3928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            dest.writeIntArray(mStateSpecs[i]);
3938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        }
3948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        dest.writeIntArray(mColors);
3958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    }
3968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    public static final Parcelable.Creator<ColorStateList> CREATOR =
3988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            new Parcelable.Creator<ColorStateList>() {
3998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        @Override
4008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        public ColorStateList[] newArray(int size) {
4018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            return new ColorStateList[size];
4028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        }
4038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
4048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        @Override
4058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        public ColorStateList createFromParcel(Parcel source) {
4068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            final int N = source.readInt();
4078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            final int[][] stateSpecs = new int[N][];
4088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            for (int i = 0; i < N; i++) {
4098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                stateSpecs[i] = source.createIntArray();
4108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            }
4118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            final int[] colors = source.createIntArray();
4128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com            return new ColorStateList(stateSpecs, colors);
4138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com        }
4148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    };
4158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com}
4168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com