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 * <selector xmlns:android="http://schemas.android.com/apk/res/android"> 498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * <item android:state_focused="true" android:color="@color/testcolor1"/> 508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * <item android:state_pressed="true" android:state_enabled="false" android:color="@color/testcolor2" /> 518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * <item android:state_enabled="false" android:color="@color/testcolor3" /> 528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * <item android:color="@color/testcolor5"/> 538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * </selector> 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 <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