1a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes/* 2a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes * Copyright (C) 2015 The Android Open Source Project 3a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes * 4a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes * Licensed under the Apache License, Version 2.0 (the "License"); 5a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes * you may not use this file except in compliance with the License. 6a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes * You may obtain a copy of the License at 7a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes * 8a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes * http://www.apache.org/licenses/LICENSE-2.0 9a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes * 10a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes * Unless required by applicable law or agreed to in writing, software 11a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes * distributed under the License is distributed on an "AS IS" BASIS, 12a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes * See the License for the specific language governing permissions and 14a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes * limitations under the License. 15a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes */ 16a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes 1766698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banespackage android.support.v7.widget; 18a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes 19a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banesimport android.content.Context; 20a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banesimport android.content.res.ColorStateList; 21a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banesimport android.graphics.Color; 22711c3df64595e2404ff6aa642ee5303f510e1dcbChris Banesimport android.support.v4.graphics.ColorUtils; 23a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banesimport android.util.TypedValue; 24a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes 2566698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesclass ThemeUtils { 26a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes 27a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes private static final ThreadLocal<TypedValue> TL_TYPED_VALUE = new ThreadLocal<>(); 28a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes 29bb1a62b3eed874aa47ea4763ac972902c77e988fChris Banes static final int[] DISABLED_STATE_SET = new int[]{-android.R.attr.state_enabled}; 30bb1a62b3eed874aa47ea4763ac972902c77e988fChris Banes static final int[] FOCUSED_STATE_SET = new int[]{android.R.attr.state_focused}; 31bb1a62b3eed874aa47ea4763ac972902c77e988fChris Banes static final int[] ACTIVATED_STATE_SET = new int[]{android.R.attr.state_activated}; 32bb1a62b3eed874aa47ea4763ac972902c77e988fChris Banes static final int[] PRESSED_STATE_SET = new int[]{android.R.attr.state_pressed}; 33bb1a62b3eed874aa47ea4763ac972902c77e988fChris Banes static final int[] CHECKED_STATE_SET = new int[]{android.R.attr.state_checked}; 34bb1a62b3eed874aa47ea4763ac972902c77e988fChris Banes static final int[] SELECTED_STATE_SET = new int[]{android.R.attr.state_selected}; 35bb1a62b3eed874aa47ea4763ac972902c77e988fChris Banes static final int[] NOT_PRESSED_OR_FOCUSED_STATE_SET = new int[]{ 36bb1a62b3eed874aa47ea4763ac972902c77e988fChris Banes -android.R.attr.state_pressed, -android.R.attr.state_focused}; 37bb1a62b3eed874aa47ea4763ac972902c77e988fChris Banes static final int[] EMPTY_STATE_SET = new int[0]; 38a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes 392aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes private static final int[] TEMP_ARRAY = new int[1]; 40a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes 412cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes public static ColorStateList createDisabledStateList(int textColor, int disabledTextColor) { 422aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes // Now create a new ColorStateList with the default color, and the new disabled 432aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes // color 442aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes final int[][] states = new int[2][]; 452aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes final int[] colors = new int[2]; 462aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes int i = 0; 47a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes 482aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes // Disabled state 492aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes states[i] = DISABLED_STATE_SET; 502aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes colors[i] = disabledTextColor; 512aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes i++; 52a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes 532aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes // Default state 542aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes states[i] = EMPTY_STATE_SET; 552aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes colors[i] = textColor; 562aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes i++; 57a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes 582aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes return new ColorStateList(states, colors); 592aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes } 602aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes 612cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes public static int getThemeAttrColor(Context context, int attr) { 622aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes TEMP_ARRAY[0] = attr; 639d5f84f33353a42e837c6b465412d1a6f2fc6eaaChris Banes TintTypedArray a = TintTypedArray.obtainStyledAttributes(context, null, TEMP_ARRAY); 642aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes try { 652aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes return a.getColor(0, 0); 662aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes } finally { 672aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes a.recycle(); 682aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes } 692aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes } 70a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes 712cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes public static ColorStateList getThemeAttrColorStateList(Context context, int attr) { 722aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes TEMP_ARRAY[0] = attr; 739d5f84f33353a42e837c6b465412d1a6f2fc6eaaChris Banes TintTypedArray a = TintTypedArray.obtainStyledAttributes(context, null, TEMP_ARRAY); 742aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes try { 752aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes return a.getColorStateList(0); 762aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes } finally { 772aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes a.recycle(); 782aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes } 792aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes } 802aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes 812cccf609662389d6a23dbc0711d5fb2e826e8c63Chris Banes public static int getDisabledThemeAttrColor(Context context, int attr) { 822aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes final ColorStateList csl = getThemeAttrColorStateList(context, attr); 832aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes if (csl != null && csl.isStateful()) { 842aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes // If the CSL is stateful, we'll assume it has a disabled state and use it 852aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes return csl.getColorForState(DISABLED_STATE_SET, csl.getDefaultColor()); 862aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes } else { 872aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes // Else, we'll generate the color using disabledAlpha from the theme 882aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes 892aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes final TypedValue tv = getTypedValue(); 902aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes // Now retrieve the disabledAlpha value from the theme 912aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, tv, true); 922aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes final float disabledAlpha = tv.getFloat(); 932aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes 942aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes return getThemeAttrColor(context, attr, disabledAlpha); 95a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes } 96a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes } 97a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes 98a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes private static TypedValue getTypedValue() { 99a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes TypedValue typedValue = TL_TYPED_VALUE.get(); 100a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes if (typedValue == null) { 101a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes typedValue = new TypedValue(); 102a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes TL_TYPED_VALUE.set(typedValue); 103a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes } 104a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes return typedValue; 105a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes } 106a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes 1072aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes static int getThemeAttrColor(Context context, int attr, float alpha) { 1082aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes final int color = getThemeAttrColor(context, attr); 1092aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes final int originalAlpha = Color.alpha(color); 1102aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes return ColorUtils.setAlphaComponent(color, Math.round(originalAlpha * alpha)); 1112aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes } 1122aeb0f4237bca35d7f650c3145354416306d4f7bChris Banes 113a73cf65dff6d7fa58907e614f95e1d3679de0a79Chris Banes} 114