TintManager.java revision 7e82b99953680915596eaf0eb35927388e574ca8
1469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes/* 2469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * Copyright (C) 2014 The Android Open Source Project 3469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * 4469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * Licensed under the Apache License, Version 2.0 (the "License"); 5469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * you may not use this file except in compliance with the License. 6469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * You may obtain a copy of the License at 7469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * 8469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * http://www.apache.org/licenses/LICENSE-2.0 9469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * 10469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * Unless required by applicable law or agreed to in writing, software 11469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * distributed under the License is distributed on an "AS IS" BASIS, 12469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * See the License for the specific language governing permissions and 14469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * limitations under the License. 15469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes */ 16469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 17469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banespackage android.support.v7.internal.widget; 18469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 19469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.content.Context; 20469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.content.res.ColorStateList; 21469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.content.res.Resources; 22469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.graphics.Color; 23469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.graphics.PorterDuff; 24469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.graphics.PorterDuffColorFilter; 25469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.graphics.drawable.Drawable; 26fd1eb27a3700de31507de34fd1bcc51830fe876cChris Banesimport android.os.Build; 27469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.support.v4.content.ContextCompat; 287e82b99953680915596eaf0eb35927388e574ca8Chris Banesimport android.support.v4.graphics.drawable.DrawableCompat; 29469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.support.v4.util.LruCache; 30469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.support.v7.appcompat.R; 31469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.util.Log; 3290075479814eb758d97b822606b448e1a521c298Chris Banesimport android.util.SparseArray; 33469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.util.TypedValue; 34a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banesimport android.view.View; 35469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 36469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes/** 37469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * @hide 38469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes */ 39a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banespublic final class TintManager { 40469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 41fd1eb27a3700de31507de34fd1bcc51830fe876cChris Banes static final boolean SHOULD_BE_USED = Build.VERSION.SDK_INT < 21; 42fd1eb27a3700de31507de34fd1bcc51830fe876cChris Banes 43469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static final String TAG = TintManager.class.getSimpleName(); 44469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static final boolean DEBUG = false; 45415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes 46415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes static final PorterDuff.Mode DEFAULT_MODE = PorterDuff.Mode.SRC_IN; 47469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 48469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static final ColorFilterLruCache COLOR_FILTER_CACHE = new ColorFilterLruCache(6); 49469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 50469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes /** 51469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * Drawables which should be tinted with the value of {@code R.attr.colorControlNormal}, 52469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * using the default mode. 53469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes */ 54469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static final int[] TINT_COLOR_CONTROL_NORMAL = { 55469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_ic_ab_back_mtrl_am_alpha, 56469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_ic_go_search_api_mtrl_alpha, 57469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_ic_search_api_mtrl_alpha, 58469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_ic_commit_search_api_mtrl_alpha, 59469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_ic_clear_mtrl_alpha, 60469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_ic_menu_share_mtrl_alpha, 61b37a31664b07243ca9e86c8dac58b9be6a417e8cChris Banes R.drawable.abc_ic_menu_copy_mtrl_am_alpha, 62b37a31664b07243ca9e86c8dac58b9be6a417e8cChris Banes R.drawable.abc_ic_menu_cut_mtrl_alpha, 63b37a31664b07243ca9e86c8dac58b9be6a417e8cChris Banes R.drawable.abc_ic_menu_selectall_mtrl_alpha, 64b37a31664b07243ca9e86c8dac58b9be6a417e8cChris Banes R.drawable.abc_ic_menu_paste_mtrl_am_alpha, 65469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_ic_menu_moreoverflow_mtrl_alpha, 66469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_ic_voice_search_api_mtrl_alpha, 67469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_textfield_search_default_mtrl_alpha, 68b645de790756e27bbe92d133216b7ac79cca7679Chris Banes R.drawable.abc_textfield_default_mtrl_alpha, 69b645de790756e27bbe92d133216b7ac79cca7679Chris Banes R.drawable.abc_ab_share_pack_mtrl_alpha 70469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes }; 71469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 72469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes /** 73469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * Drawables which should be tinted with the value of {@code R.attr.colorControlActivated}, 74469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * using the default mode. 75469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes */ 76469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static final int[] TINT_COLOR_CONTROL_ACTIVATED = { 77469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_textfield_activated_mtrl_alpha, 7814f8f0dfae09445074dc0f7b5bbe5732d6922da7Chris Banes R.drawable.abc_textfield_search_activated_mtrl_alpha, 79911642499da7d796aa1e7c19178c3552a590f48bChris Banes R.drawable.abc_cab_background_top_mtrl_alpha, 80911642499da7d796aa1e7c19178c3552a590f48bChris Banes R.drawable.abc_text_cursor_mtrl_alpha 81469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes }; 82469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 83469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes /** 84469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * Drawables which should be tinted with the value of {@code android.R.attr.colorBackground}, 85469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * using the {@link android.graphics.PorterDuff.Mode#MULTIPLY} mode. 86469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes */ 87469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static final int[] TINT_COLOR_BACKGROUND_MULTIPLY = { 881073132946bb0a53a788949fe4c060f72051cd57Chris Banes R.drawable.abc_popup_background_mtrl_mult, 8957c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes R.drawable.abc_cab_background_internal_bg, 9057c6de90985a63358129b99b9f0cd4d6afe887d6Chris Banes R.drawable.abc_menu_hardkey_panel_mtrl_mult 91469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes }; 92469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 93469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes /** 94469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * Drawables which should be tinted using a state list containing values of 95469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * {@code R.attr.colorControlNormal} and {@code R.attr.colorControlActivated} 96469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes */ 97469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static final int[] TINT_COLOR_CONTROL_STATE_LIST = { 98469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_edit_text_material, 99469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_tab_indicator_material, 100469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_textfield_search_material, 101415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes R.drawable.abc_spinner_mtrl_am_alpha, 102415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes R.drawable.abc_btn_check_material, 103f67cc46fd515df18c4b70dce9e5dcdd4e3245cd8Chris Banes R.drawable.abc_btn_radio_material, 104a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes R.drawable.abc_spinner_textfield_background_material, 10590075479814eb758d97b822606b448e1a521c298Chris Banes R.drawable.abc_ratingbar_full_material, 10690075479814eb758d97b822606b448e1a521c298Chris Banes R.drawable.abc_switch_track_mtrl_alpha, 10790075479814eb758d97b822606b448e1a521c298Chris Banes R.drawable.abc_switch_thumb_material, 10816e8d4dd91083260223c007c797e46bc8f631055Chris Banes R.drawable.abc_btn_default_mtrl_shape, 10916e8d4dd91083260223c007c797e46bc8f631055Chris Banes R.drawable.abc_btn_borderless_material 110469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes }; 111469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 112469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes /** 113469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * Drawables which contain other drawables which should be tinted. The child drawable IDs 114469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * should be defined in one of the arrays above. 115469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes */ 116469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static final int[] CONTAINERS_WITH_TINT_CHILDREN = { 1171073132946bb0a53a788949fe4c060f72051cd57Chris Banes R.drawable.abc_cab_background_top_material 118469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes }; 119469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 120469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private final Context mContext; 121469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private final Resources mResources; 122469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private final TypedValue mTypedValue; 123469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 12490075479814eb758d97b822606b448e1a521c298Chris Banes private final SparseArray<ColorStateList> mColorStateLists; 125469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private ColorStateList mDefaultColorStateList; 126469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 127469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes /** 128469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * A helper method to instantiate a {@link TintManager} and then call {@link #getDrawable(int)}. 129469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * This method should not be used routinely. 130469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes */ 131469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes public static Drawable getDrawable(Context context, int resId) { 132b37a31664b07243ca9e86c8dac58b9be6a417e8cChris Banes if (isInTintList(resId)) { 133911642499da7d796aa1e7c19178c3552a590f48bChris Banes final TintManager tm = (context instanceof TintContextWrapper) 134911642499da7d796aa1e7c19178c3552a590f48bChris Banes ? ((TintContextWrapper) context).getTintManager() 135911642499da7d796aa1e7c19178c3552a590f48bChris Banes : new TintManager(context); 136911642499da7d796aa1e7c19178c3552a590f48bChris Banes return tm.getDrawable(resId); 137b37a31664b07243ca9e86c8dac58b9be6a417e8cChris Banes } else { 138b37a31664b07243ca9e86c8dac58b9be6a417e8cChris Banes return ContextCompat.getDrawable(context, resId); 139b37a31664b07243ca9e86c8dac58b9be6a417e8cChris Banes } 140469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 141469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 142469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes public TintManager(Context context) { 14390075479814eb758d97b822606b448e1a521c298Chris Banes mColorStateLists = new SparseArray<>(); 144469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes mContext = context; 145469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes mTypedValue = new TypedValue(); 146911642499da7d796aa1e7c19178c3552a590f48bChris Banes mResources = new TintResources(context.getResources(), this); 147911642499da7d796aa1e7c19178c3552a590f48bChris Banes } 148911642499da7d796aa1e7c19178c3552a590f48bChris Banes 149911642499da7d796aa1e7c19178c3552a590f48bChris Banes Resources getResources() { 150911642499da7d796aa1e7c19178c3552a590f48bChris Banes return mResources; 151469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 152469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 153469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes public Drawable getDrawable(int resId) { 154469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes Drawable drawable = ContextCompat.getDrawable(mContext, resId); 155469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 156469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes if (drawable != null) { 157c7d6de1eb6692c627a02a4ed439a8a4b849ca66cChris Banes drawable = drawable.mutate(); 158c7d6de1eb6692c627a02a4ed439a8a4b849ca66cChris Banes 159469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes if (arrayContains(TINT_COLOR_CONTROL_STATE_LIST, resId)) { 160a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes ColorStateList colorStateList = getColorStateListForKnownDrawableId(resId); 161a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes PorterDuff.Mode tintMode = DEFAULT_MODE; 162a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes if (resId == R.drawable.abc_switch_thumb_material) { 163a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes tintMode = PorterDuff.Mode.MULTIPLY; 164a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes } 165a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes 166a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes if (colorStateList != null) { 1677e82b99953680915596eaf0eb35927388e574ca8Chris Banes drawable = DrawableCompat.wrap(drawable); 1687e82b99953680915596eaf0eb35927388e574ca8Chris Banes DrawableCompat.setTintList(drawable, colorStateList); 1697e82b99953680915596eaf0eb35927388e574ca8Chris Banes DrawableCompat.setTintMode(drawable, tintMode); 170a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes } 171469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } else if (arrayContains(CONTAINERS_WITH_TINT_CHILDREN, resId)) { 172469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes drawable = mResources.getDrawable(resId); 173469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } else { 174469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes tintDrawable(resId, drawable); 175469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 176469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 177469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes return drawable; 178469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 179469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 1800517b282bde8b9a0377dfe5bc4756405a196adb4Chris Banes void tintDrawable(final int resId, final Drawable drawable) { 181469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes PorterDuff.Mode tintMode = null; 182469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes boolean colorAttrSet = false; 183469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes int colorAttr = 0; 1840517b282bde8b9a0377dfe5bc4756405a196adb4Chris Banes int alpha = -1; 185469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 186469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes if (arrayContains(TINT_COLOR_CONTROL_NORMAL, resId)) { 187469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colorAttr = R.attr.colorControlNormal; 188469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colorAttrSet = true; 189469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } else if (arrayContains(TINT_COLOR_CONTROL_ACTIVATED, resId)) { 190469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colorAttr = R.attr.colorControlActivated; 191469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colorAttrSet = true; 192469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } else if (arrayContains(TINT_COLOR_BACKGROUND_MULTIPLY, resId)) { 193469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colorAttr = android.R.attr.colorBackground; 194469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colorAttrSet = true; 195469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes tintMode = PorterDuff.Mode.MULTIPLY; 1960517b282bde8b9a0377dfe5bc4756405a196adb4Chris Banes } else if (resId == R.drawable.abc_list_divider_mtrl_alpha) { 1970517b282bde8b9a0377dfe5bc4756405a196adb4Chris Banes colorAttr = android.R.attr.colorForeground; 1980517b282bde8b9a0377dfe5bc4756405a196adb4Chris Banes colorAttrSet = true; 1990517b282bde8b9a0377dfe5bc4756405a196adb4Chris Banes alpha = Math.round(0.16f * 255); 200469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 201469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 202f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes if (colorAttrSet) { 203469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes if (tintMode == null) { 204469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes tintMode = DEFAULT_MODE; 205469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 206f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes final int color = getThemeAttrColor(colorAttr); 207469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 208a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes tintDrawableUsingColorFilter(drawable, color, tintMode); 209469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 2100517b282bde8b9a0377dfe5bc4756405a196adb4Chris Banes if (alpha != -1) { 2110517b282bde8b9a0377dfe5bc4756405a196adb4Chris Banes drawable.setAlpha(alpha); 2120517b282bde8b9a0377dfe5bc4756405a196adb4Chris Banes } 2130517b282bde8b9a0377dfe5bc4756405a196adb4Chris Banes 214469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes if (DEBUG) { 215469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes Log.d(TAG, "Tinted Drawable ID: " + mResources.getResourceName(resId) + 216469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes " with color: #" + Integer.toHexString(color)); 217469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 218469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 219469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 220469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 221469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static boolean arrayContains(int[] array, int value) { 222469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes for (int id : array) { 223469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes if (id == value) { 224469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes return true; 225469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 226469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 227469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes return false; 228469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 229469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 230b37a31664b07243ca9e86c8dac58b9be6a417e8cChris Banes private static boolean isInTintList(int drawableId) { 231b37a31664b07243ca9e86c8dac58b9be6a417e8cChris Banes return arrayContains(TINT_COLOR_BACKGROUND_MULTIPLY, drawableId) || 232b37a31664b07243ca9e86c8dac58b9be6a417e8cChris Banes arrayContains(TINT_COLOR_CONTROL_NORMAL, drawableId) || 233b37a31664b07243ca9e86c8dac58b9be6a417e8cChris Banes arrayContains(TINT_COLOR_CONTROL_ACTIVATED, drawableId) || 234b37a31664b07243ca9e86c8dac58b9be6a417e8cChris Banes arrayContains(TINT_COLOR_CONTROL_STATE_LIST, drawableId) || 235b37a31664b07243ca9e86c8dac58b9be6a417e8cChris Banes arrayContains(CONTAINERS_WITH_TINT_CHILDREN, drawableId); 236b37a31664b07243ca9e86c8dac58b9be6a417e8cChris Banes } 237b37a31664b07243ca9e86c8dac58b9be6a417e8cChris Banes 238a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes ColorStateList getColorStateList(int resId) { 239a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes return arrayContains(TINT_COLOR_CONTROL_STATE_LIST, resId) 240a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes ? getColorStateListForKnownDrawableId(resId) 241a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes : null; 242a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes } 243a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes 244a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes private ColorStateList getColorStateListForKnownDrawableId(int resId) { 24590075479814eb758d97b822606b448e1a521c298Chris Banes // Try the cache first 24690075479814eb758d97b822606b448e1a521c298Chris Banes ColorStateList colorStateList = mColorStateLists.get(resId); 24790075479814eb758d97b822606b448e1a521c298Chris Banes 24890075479814eb758d97b822606b448e1a521c298Chris Banes if (colorStateList == null) { 24990075479814eb758d97b822606b448e1a521c298Chris Banes // ...if the cache did not contain a color state list, try and create 25090075479814eb758d97b822606b448e1a521c298Chris Banes if (resId == R.drawable.abc_edit_text_material) { 25190075479814eb758d97b822606b448e1a521c298Chris Banes colorStateList = createEditTextColorStateList(); 25290075479814eb758d97b822606b448e1a521c298Chris Banes } else if (resId == R.drawable.abc_switch_track_mtrl_alpha) { 25390075479814eb758d97b822606b448e1a521c298Chris Banes colorStateList = createSwitchTrackColorStateList(); 25490075479814eb758d97b822606b448e1a521c298Chris Banes } else if (resId == R.drawable.abc_switch_thumb_material) { 25590075479814eb758d97b822606b448e1a521c298Chris Banes colorStateList = createSwitchThumbColorStateList(); 25616e8d4dd91083260223c007c797e46bc8f631055Chris Banes } else if (resId == R.drawable.abc_btn_default_mtrl_shape 25716e8d4dd91083260223c007c797e46bc8f631055Chris Banes || resId == R.drawable.abc_btn_borderless_material) { 25890075479814eb758d97b822606b448e1a521c298Chris Banes colorStateList = createButtonColorStateList(); 259cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes } else if (resId == R.drawable.abc_spinner_mtrl_am_alpha 260cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes || resId == R.drawable.abc_spinner_textfield_background_material) { 261cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes colorStateList = createSpinnerColorStateList(); 26290075479814eb758d97b822606b448e1a521c298Chris Banes } else { 26390075479814eb758d97b822606b448e1a521c298Chris Banes // If we don't have an explicit color state list for this Drawable, use the default 26490075479814eb758d97b822606b448e1a521c298Chris Banes colorStateList = getDefaultColorStateList(); 26590075479814eb758d97b822606b448e1a521c298Chris Banes } 266a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes 26790075479814eb758d97b822606b448e1a521c298Chris Banes // ..and add it to the cache 26890075479814eb758d97b822606b448e1a521c298Chris Banes mColorStateLists.append(resId, colorStateList); 26990075479814eb758d97b822606b448e1a521c298Chris Banes } 270a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes return colorStateList; 27190075479814eb758d97b822606b448e1a521c298Chris Banes } 27290075479814eb758d97b822606b448e1a521c298Chris Banes 273469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private ColorStateList getDefaultColorStateList() { 274469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes if (mDefaultColorStateList == null) { 275469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes /** 276469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * Generate the default color state list which uses the colorControl attributes. 277469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * Order is important here. The default enabled state needs to go at the bottom. 278469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes */ 279469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 280469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes final int colorControlNormal = getThemeAttrColor(R.attr.colorControlNormal); 281469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes final int colorControlActivated = getThemeAttrColor(R.attr.colorControlActivated); 282469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 283469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes final int[][] states = new int[7][]; 284469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes final int[] colors = new int[7]; 285469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes int i = 0; 286469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 287c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes // Disabled state 288c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes states[i] = new int[] { -android.R.attr.state_enabled }; 289c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes colors[i] = getDisabledThemeAttrColor(R.attr.colorControlNormal); 290469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes i++; 291469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 292c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes states[i] = new int[] { android.R.attr.state_focused }; 293469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colors[i] = colorControlActivated; 294469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes i++; 295469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 296c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes states[i] = new int[] { android.R.attr.state_activated }; 297469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colors[i] = colorControlActivated; 298469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes i++; 299469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 300c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes states[i] = new int[] { android.R.attr.state_pressed }; 301469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colors[i] = colorControlActivated; 302469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes i++; 303469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 304c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes states[i] = new int[] { android.R.attr.state_checked }; 305469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colors[i] = colorControlActivated; 306469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes i++; 307469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 308c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes states[i] = new int[] { android.R.attr.state_selected }; 309c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes colors[i] = colorControlActivated; 310469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes i++; 311469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 312c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes // Default enabled state 313469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes states[i] = new int[0]; 314c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes colors[i] = colorControlNormal; 315469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes i++; 316469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 317469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes mDefaultColorStateList = new ColorStateList(states, colors); 318469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 319469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes return mDefaultColorStateList; 320469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 321469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 32290075479814eb758d97b822606b448e1a521c298Chris Banes private ColorStateList createSwitchTrackColorStateList() { 32390075479814eb758d97b822606b448e1a521c298Chris Banes final int[][] states = new int[3][]; 32490075479814eb758d97b822606b448e1a521c298Chris Banes final int[] colors = new int[3]; 32590075479814eb758d97b822606b448e1a521c298Chris Banes int i = 0; 326415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes 32790075479814eb758d97b822606b448e1a521c298Chris Banes // Disabled state 32890075479814eb758d97b822606b448e1a521c298Chris Banes states[i] = new int[]{-android.R.attr.state_enabled}; 32990075479814eb758d97b822606b448e1a521c298Chris Banes colors[i] = getThemeAttrColor(android.R.attr.colorForeground, 0.1f); 33090075479814eb758d97b822606b448e1a521c298Chris Banes i++; 331415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes 33290075479814eb758d97b822606b448e1a521c298Chris Banes states[i] = new int[]{android.R.attr.state_checked}; 33390075479814eb758d97b822606b448e1a521c298Chris Banes colors[i] = getThemeAttrColor(R.attr.colorControlActivated, 0.3f); 33490075479814eb758d97b822606b448e1a521c298Chris Banes i++; 335415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes 33690075479814eb758d97b822606b448e1a521c298Chris Banes // Default enabled state 33790075479814eb758d97b822606b448e1a521c298Chris Banes states[i] = new int[0]; 33890075479814eb758d97b822606b448e1a521c298Chris Banes colors[i] = getThemeAttrColor(android.R.attr.colorForeground, 0.3f); 33990075479814eb758d97b822606b448e1a521c298Chris Banes i++; 340415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes 34190075479814eb758d97b822606b448e1a521c298Chris Banes return new ColorStateList(states, colors); 342415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes } 343415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes 34490075479814eb758d97b822606b448e1a521c298Chris Banes private ColorStateList createSwitchThumbColorStateList() { 34590075479814eb758d97b822606b448e1a521c298Chris Banes final int[][] states = new int[3][]; 34690075479814eb758d97b822606b448e1a521c298Chris Banes final int[] colors = new int[3]; 34790075479814eb758d97b822606b448e1a521c298Chris Banes int i = 0; 348415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes 349414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes final ColorStateList thumbColor = getThemeAttrColorStateList(R.attr.colorSwitchThumbNormal); 350415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes 351414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes if (thumbColor != null && thumbColor.isStateful()) { 352414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes // If colorSwitchThumbNormal is a valid ColorStateList, extract the default and 353414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes // disabled colors from it 354415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes 355414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes // Disabled state 356414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes states[i] = new int[]{-android.R.attr.state_enabled}; 357414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes colors[i] = thumbColor.getColorForState(states[i], 0); 358414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes i++; 359414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes 360414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes states[i] = new int[]{android.R.attr.state_checked}; 361414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes colors[i] = getThemeAttrColor(R.attr.colorControlActivated); 362414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes i++; 363414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes 364414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes // Default enabled state 365414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes states[i] = new int[0]; 366414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes colors[i] = thumbColor.getDefaultColor(); 367414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes i++; 368414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes } else { 369414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes // Else we'll use an approximation using the default disabled alpha 370414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes 371414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes // Disabled state 372414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes states[i] = new int[]{-android.R.attr.state_enabled}; 373414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes colors[i] = getDisabledThemeAttrColor(R.attr.colorSwitchThumbNormal); 374414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes i++; 375414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes 376414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes states[i] = new int[]{android.R.attr.state_checked}; 377414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes colors[i] = getThemeAttrColor(R.attr.colorControlActivated); 378414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes i++; 379414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes 380414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes // Default enabled state 381414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes states[i] = new int[0]; 382414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes colors[i] = getThemeAttrColor(R.attr.colorSwitchThumbNormal); 383414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes i++; 384414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes } 385415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes 38690075479814eb758d97b822606b448e1a521c298Chris Banes return new ColorStateList(states, colors); 387415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes } 388415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes 38990075479814eb758d97b822606b448e1a521c298Chris Banes private ColorStateList createEditTextColorStateList() { 39090075479814eb758d97b822606b448e1a521c298Chris Banes final int[][] states = new int[3][]; 39190075479814eb758d97b822606b448e1a521c298Chris Banes final int[] colors = new int[3]; 39290075479814eb758d97b822606b448e1a521c298Chris Banes int i = 0; 393a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes 39490075479814eb758d97b822606b448e1a521c298Chris Banes // Disabled state 39590075479814eb758d97b822606b448e1a521c298Chris Banes states[i] = new int[]{-android.R.attr.state_enabled}; 39690075479814eb758d97b822606b448e1a521c298Chris Banes colors[i] = getDisabledThemeAttrColor(R.attr.colorControlNormal); 39790075479814eb758d97b822606b448e1a521c298Chris Banes i++; 398a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes 39990075479814eb758d97b822606b448e1a521c298Chris Banes states[i] = new int[]{-android.R.attr.state_pressed, -android.R.attr.state_focused}; 40090075479814eb758d97b822606b448e1a521c298Chris Banes colors[i] = getThemeAttrColor(R.attr.colorControlNormal); 40190075479814eb758d97b822606b448e1a521c298Chris Banes i++; 402a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes 40390075479814eb758d97b822606b448e1a521c298Chris Banes // Default enabled state 40490075479814eb758d97b822606b448e1a521c298Chris Banes states[i] = new int[0]; 40590075479814eb758d97b822606b448e1a521c298Chris Banes colors[i] = getThemeAttrColor(R.attr.colorControlActivated); 40690075479814eb758d97b822606b448e1a521c298Chris Banes i++; 407a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes 40890075479814eb758d97b822606b448e1a521c298Chris Banes return new ColorStateList(states, colors); 40990075479814eb758d97b822606b448e1a521c298Chris Banes } 410a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes 41190075479814eb758d97b822606b448e1a521c298Chris Banes private ColorStateList createButtonColorStateList() { 41290075479814eb758d97b822606b448e1a521c298Chris Banes final int[][] states = new int[4][]; 41390075479814eb758d97b822606b448e1a521c298Chris Banes final int[] colors = new int[4]; 41490075479814eb758d97b822606b448e1a521c298Chris Banes int i = 0; 41590075479814eb758d97b822606b448e1a521c298Chris Banes 41690075479814eb758d97b822606b448e1a521c298Chris Banes // Disabled state 41790075479814eb758d97b822606b448e1a521c298Chris Banes states[i] = new int[]{-android.R.attr.state_enabled}; 41890075479814eb758d97b822606b448e1a521c298Chris Banes colors[i] = getDisabledThemeAttrColor(R.attr.colorButtonNormal); 41990075479814eb758d97b822606b448e1a521c298Chris Banes i++; 42090075479814eb758d97b822606b448e1a521c298Chris Banes 42190075479814eb758d97b822606b448e1a521c298Chris Banes states[i] = new int[]{android.R.attr.state_pressed}; 42290075479814eb758d97b822606b448e1a521c298Chris Banes colors[i] = getThemeAttrColor(R.attr.colorControlHighlight); 42390075479814eb758d97b822606b448e1a521c298Chris Banes i++; 42490075479814eb758d97b822606b448e1a521c298Chris Banes 42590075479814eb758d97b822606b448e1a521c298Chris Banes states[i] = new int[]{android.R.attr.state_focused}; 42690075479814eb758d97b822606b448e1a521c298Chris Banes colors[i] = getThemeAttrColor(R.attr.colorControlHighlight); 42790075479814eb758d97b822606b448e1a521c298Chris Banes i++; 42890075479814eb758d97b822606b448e1a521c298Chris Banes 42990075479814eb758d97b822606b448e1a521c298Chris Banes // Default enabled state 43090075479814eb758d97b822606b448e1a521c298Chris Banes states[i] = new int[0]; 43190075479814eb758d97b822606b448e1a521c298Chris Banes colors[i] = getThemeAttrColor(R.attr.colorButtonNormal); 43290075479814eb758d97b822606b448e1a521c298Chris Banes i++; 43390075479814eb758d97b822606b448e1a521c298Chris Banes 43490075479814eb758d97b822606b448e1a521c298Chris Banes return new ColorStateList(states, colors); 435a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes } 436a9585dae398a69dd67797e7ca86f44ffcabd9e86Chris Banes 437cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes private ColorStateList createSpinnerColorStateList() { 438cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes final int[][] states = new int[3][]; 439cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes final int[] colors = new int[3]; 440cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes int i = 0; 441cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes 442cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes // Disabled state 443cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes states[i] = new int[]{-android.R.attr.state_enabled}; 444cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes colors[i] = getDisabledThemeAttrColor(R.attr.colorControlNormal); 445cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes i++; 446cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes 447cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes states[i] = new int[]{-android.R.attr.state_pressed, -android.R.attr.state_focused}; 448cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes colors[i] = getThemeAttrColor(R.attr.colorControlNormal); 449cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes i++; 450cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes 451cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes states[i] = new int[0]; 452cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes colors[i] = getThemeAttrColor(R.attr.colorControlActivated); 453cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes i++; 454cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes 455cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes return new ColorStateList(states, colors); 456cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes } 457cdd1b1d70cefeb052c2b506738b396f2f982e519Chris Banes 45890075479814eb758d97b822606b448e1a521c298Chris Banes private int getThemeAttrColor(int attr) { 459f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes if (mContext.getTheme().resolveAttribute(attr, mTypedValue, true)) { 460f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes if (mTypedValue.type >= TypedValue.TYPE_FIRST_INT 461f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes && mTypedValue.type <= TypedValue.TYPE_LAST_INT) { 462f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes return mTypedValue.data; 463f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes } else if (mTypedValue.type == TypedValue.TYPE_STRING) { 464f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes return mResources.getColor(mTypedValue.resourceId); 465f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes } 466f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes } 467f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes return 0; 468469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 469469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 470414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes private ColorStateList getThemeAttrColorStateList(int attr) { 471414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes if (mContext.getTheme().resolveAttribute(attr, mTypedValue, true)) { 472414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes if (mTypedValue.type == TypedValue.TYPE_STRING) { 473414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes return mResources.getColorStateList(mTypedValue.resourceId); 474414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes } 475414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes } 476414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes return null; 477414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes } 478414f52397a88d52a783a31d4c098bc3bec632b8dChris Banes 47990075479814eb758d97b822606b448e1a521c298Chris Banes private int getThemeAttrColor(int attr, float alpha) { 480f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes final int color = getThemeAttrColor(attr); 481c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes final int originalAlpha = Color.alpha(color); 482c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes 483415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes // Return the color, multiplying the original alpha by the disabled value 484415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes return (color & 0x00ffffff) | (Math.round(originalAlpha * alpha) << 24); 485415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes } 486415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes 48790075479814eb758d97b822606b448e1a521c298Chris Banes private int getDisabledThemeAttrColor(int attr) { 488c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes // Now retrieve the disabledAlpha value from the theme 489c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes mContext.getTheme().resolveAttribute(android.R.attr.disabledAlpha, mTypedValue, true); 490c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes final float disabledAlpha = mTypedValue.getFloat(); 491c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes 492415f740df4981ef2f5fb462a50c7cf095cc21128Chris Banes return getThemeAttrColor(attr, disabledAlpha); 493c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes } 494c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes 495469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static class ColorFilterLruCache extends LruCache<Integer, PorterDuffColorFilter> { 496469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 497469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes public ColorFilterLruCache(int maxSize) { 498469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes super(maxSize); 499469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 500469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 501469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes PorterDuffColorFilter get(int color, PorterDuff.Mode mode) { 502469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes return get(generateCacheKey(color, mode)); 503469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 504469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 505469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes PorterDuffColorFilter put(int color, PorterDuff.Mode mode, PorterDuffColorFilter filter) { 506469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes return put(generateCacheKey(color, mode), filter); 507469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 508469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 509469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static int generateCacheKey(int color, PorterDuff.Mode mode) { 510469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes int hashCode = 1; 511469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes hashCode = 31 * hashCode + color; 512469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes hashCode = 31 * hashCode + mode.hashCode(); 513469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes return hashCode; 514469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 515469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 516a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes 517a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes public static void tintViewBackground(View view, TintInfo tint) { 518a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes final Drawable background = view.getBackground(); 519a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes if (tint.mTintList != null) { 520a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes tintDrawableUsingColorFilter( 521a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes background, 522a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes tint.mTintList.getColorForState(view.getDrawableState(), 523a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes tint.mTintList.getDefaultColor()), 524a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes tint.mTintMode != null ? tint.mTintMode : DEFAULT_MODE); 525a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes } else { 526a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes background.clearColorFilter(); 527a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes } 528a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes } 529a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes 530a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes private static void tintDrawableUsingColorFilter(Drawable drawable, int color, 531a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes PorterDuff.Mode mode) { 532a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes // First, lets see if the cache already contains the color filter 533a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes PorterDuffColorFilter filter = COLOR_FILTER_CACHE.get(color, mode); 534a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes 535a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes if (filter == null) { 536a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes // Cache miss, so create a color filter and add it to the cache 537a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes filter = new PorterDuffColorFilter(color, mode); 538a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes COLOR_FILTER_CACHE.put(color, mode, filter); 539a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes } 540a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes 541a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes drawable.setColorFilter(filter); 542a5f106fbd09335ae504c39b1ee1e0caa3f1238e3Chris Banes } 543469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes} 544