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 * <selector xmlns:android="http://schemas.android.com/apk/res/android"> 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <item android:state_focused="true" android:color="@color/testcolor1"/> 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <item android:state_pressed="true" android:state_enabled="false" android:color="@color/testcolor2" /> 5179dc8ccddd846816d4e0e55405ad0dbefa5b0ff6Romain Guy * <item android:state_enabled="false" android:color="@color/testcolor3" /> 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <item android:color="@color/testcolor5"/> 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </selector> 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 <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