1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.support.v7.widget;
18 
19 import android.content.Context;
20 import android.content.res.ColorStateList;
21 import android.graphics.Color;
22 import android.support.v4.graphics.ColorUtils;
23 import android.util.TypedValue;
24 
25 class ThemeUtils {
26 
27     private static final ThreadLocal<TypedValue> TL_TYPED_VALUE = new ThreadLocal<>();
28 
29     static final int[] DISABLED_STATE_SET = new int[]{-android.R.attr.state_enabled};
30     static final int[] FOCUSED_STATE_SET = new int[]{android.R.attr.state_focused};
31     static final int[] ACTIVATED_STATE_SET = new int[]{android.R.attr.state_activated};
32     static final int[] PRESSED_STATE_SET = new int[]{android.R.attr.state_pressed};
33     static final int[] CHECKED_STATE_SET = new int[]{android.R.attr.state_checked};
34     static final int[] SELECTED_STATE_SET = new int[]{android.R.attr.state_selected};
35     static final int[] NOT_PRESSED_OR_FOCUSED_STATE_SET = new int[]{
36             -android.R.attr.state_pressed, -android.R.attr.state_focused};
37     static final int[] EMPTY_STATE_SET = new int[0];
38 
39     private static final int[] TEMP_ARRAY = new int[1];
40 
createDisabledStateList(int textColor, int disabledTextColor)41     public static ColorStateList createDisabledStateList(int textColor, int disabledTextColor) {
42         // Now create a new ColorStateList with the default color, and the new disabled
43         // color
44         final int[][] states = new int[2][];
45         final int[] colors = new int[2];
46         int i = 0;
47 
48         // Disabled state
49         states[i] = DISABLED_STATE_SET;
50         colors[i] = disabledTextColor;
51         i++;
52 
53         // Default state
54         states[i] = EMPTY_STATE_SET;
55         colors[i] = textColor;
56         i++;
57 
58         return new ColorStateList(states, colors);
59     }
60 
getThemeAttrColor(Context context, int attr)61     public static int getThemeAttrColor(Context context, int attr) {
62         TEMP_ARRAY[0] = attr;
63         TintTypedArray a = TintTypedArray.obtainStyledAttributes(context, null, TEMP_ARRAY);
64         try {
65             return a.getColor(0, 0);
66         } finally {
67             a.recycle();
68         }
69     }
70 
getThemeAttrColorStateList(Context context, int attr)71     public static ColorStateList getThemeAttrColorStateList(Context context, int attr) {
72         TEMP_ARRAY[0] = attr;
73         TintTypedArray a = TintTypedArray.obtainStyledAttributes(context, null, TEMP_ARRAY);
74         try {
75             return a.getColorStateList(0);
76         } finally {
77             a.recycle();
78         }
79     }
80 
getDisabledThemeAttrColor(Context context, int attr)81     public static int getDisabledThemeAttrColor(Context context, int attr) {
82         final ColorStateList csl = getThemeAttrColorStateList(context, attr);
83         if (csl != null && csl.isStateful()) {
84             // If the CSL is stateful, we'll assume it has a disabled state and use it
85             return csl.getColorForState(DISABLED_STATE_SET, csl.getDefaultColor());
86         } else {
87             // Else, we'll generate the color using disabledAlpha from the theme
88 
89             final TypedValue tv = getTypedValue();
90             // Now retrieve the disabledAlpha value from the theme
91             context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, tv, true);
92             final float disabledAlpha = tv.getFloat();
93 
94             return getThemeAttrColor(context, attr, disabledAlpha);
95         }
96     }
97 
getTypedValue()98     private static TypedValue getTypedValue() {
99         TypedValue typedValue = TL_TYPED_VALUE.get();
100         if (typedValue == null) {
101             typedValue = new TypedValue();
102             TL_TYPED_VALUE.set(typedValue);
103         }
104         return typedValue;
105     }
106 
getThemeAttrColor(Context context, int attr, float alpha)107     static int getThemeAttrColor(Context context, int attr, float alpha) {
108         final int color = getThemeAttrColor(context, attr);
109         final int originalAlpha = Color.alpha(color);
110         return ColorUtils.setAlphaComponent(color, Math.round(originalAlpha * alpha));
111     }
112 
113 }
114