AppCompatDrawableManager.java revision 14f8f0dfae09445074dc0f7b5bbe5732d6922da7
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; 26469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.support.v4.content.ContextCompat; 27469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.support.v4.util.LruCache; 28469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.support.v7.appcompat.R; 29469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.util.Log; 30469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.util.TypedValue; 31469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 32469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes/** 33469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * @hide 34469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes */ 35469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banespublic class TintManager { 36469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 37469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static final String TAG = TintManager.class.getSimpleName(); 38469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static final boolean DEBUG = false; 39469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static final PorterDuff.Mode DEFAULT_MODE = PorterDuff.Mode.SRC_IN; 40469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 41469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static final ColorFilterLruCache COLOR_FILTER_CACHE = new ColorFilterLruCache(6); 42469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 43469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes /** 44469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * Drawables which should be tinted with the value of {@code R.attr.colorControlNormal}, 45469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * using the default mode. 46469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes */ 47469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static final int[] TINT_COLOR_CONTROL_NORMAL = { 48469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_ic_ab_back_mtrl_am_alpha, 49469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_ic_go_search_api_mtrl_alpha, 50469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_ic_search_api_mtrl_alpha, 51469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_ic_commit_search_api_mtrl_alpha, 52469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_ic_clear_mtrl_alpha, 53469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_ic_menu_share_mtrl_alpha, 54469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_ic_menu_moreoverflow_mtrl_alpha, 55469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_ic_voice_search_api_mtrl_alpha, 56469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_textfield_search_default_mtrl_alpha, 57c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes R.drawable.abc_textfield_default_mtrl_alpha, 58c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes R.drawable.abc_list_divider_mtrl_alpha 59469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes }; 60469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 61469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes /** 62469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * Drawables which should be tinted with the value of {@code R.attr.colorControlActivated}, 63469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * using the default mode. 64469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes */ 65469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static final int[] TINT_COLOR_CONTROL_ACTIVATED = { 66469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_textfield_activated_mtrl_alpha, 6714f8f0dfae09445074dc0f7b5bbe5732d6922da7Chris Banes R.drawable.abc_textfield_search_activated_mtrl_alpha, 6814f8f0dfae09445074dc0f7b5bbe5732d6922da7Chris Banes R.drawable.abc_cab_background_top_mtrl_alpha 69469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes }; 70469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 71469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes /** 72469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * Drawables which should be tinted with the value of {@code android.R.attr.colorBackground}, 73469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * using the {@link android.graphics.PorterDuff.Mode#MULTIPLY} mode. 74469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes */ 75469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static final int[] TINT_COLOR_BACKGROUND_MULTIPLY = { 761073132946bb0a53a788949fe4c060f72051cd57Chris Banes R.drawable.abc_popup_background_mtrl_mult, 771073132946bb0a53a788949fe4c060f72051cd57Chris Banes R.drawable.abc_cab_background_internal_bg 78469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes }; 79469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 80469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes /** 81469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * Drawables which should be tinted using a state list containing values of 82469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * {@code R.attr.colorControlNormal} and {@code R.attr.colorControlActivated} 83469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes */ 84469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static final int[] TINT_COLOR_CONTROL_STATE_LIST = { 85469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_edit_text_material, 86469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_tab_indicator_material, 87469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_textfield_search_material, 88469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes R.drawable.abc_spinner_mtrl_am_alpha 89469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes }; 90469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 91469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes /** 92469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * Drawables which contain other drawables which should be tinted. The child drawable IDs 93469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * should be defined in one of the arrays above. 94469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes */ 95469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static final int[] CONTAINERS_WITH_TINT_CHILDREN = { 961073132946bb0a53a788949fe4c060f72051cd57Chris Banes R.drawable.abc_cab_background_top_material 97469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes }; 98469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 99469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private final Context mContext; 100469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private final Resources mResources; 101469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private final TypedValue mTypedValue; 102469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 103469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private ColorStateList mDefaultColorStateList; 104469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 105469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes /** 106469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * A helper method to instantiate a {@link TintManager} and then call {@link #getDrawable(int)}. 107469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * This method should not be used routinely. 108469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes */ 109469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes public static Drawable getDrawable(Context context, int resId) { 110469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes TintManager tintManager = new TintManager(context); 111469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes return tintManager.getDrawable(resId); 112469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 113469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 114469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes public TintManager(Context context) { 115469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes mContext = context; 116469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes mResources = new TintResources(context.getResources(), this); 117469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes mTypedValue = new TypedValue(); 118469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 119469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 120469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes public Drawable getDrawable(int resId) { 121469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes Drawable drawable = ContextCompat.getDrawable(mContext, resId); 122469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 123469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes if (drawable != null) { 124469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes if (arrayContains(TINT_COLOR_CONTROL_STATE_LIST, resId)) { 125469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes drawable = new TintDrawableWrapper(drawable, getDefaultColorStateList()); 126469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } else if (arrayContains(CONTAINERS_WITH_TINT_CHILDREN, resId)) { 127469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes drawable = mResources.getDrawable(resId); 128469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } else { 129469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes tintDrawable(resId, drawable); 130469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 131469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 132469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes return drawable; 133469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 134469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 135469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes void tintDrawable(int resId, Drawable drawable) { 136469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes PorterDuff.Mode tintMode = null; 137469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes boolean colorAttrSet = false; 138469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes int colorAttr = 0; 139469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 140469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes if (arrayContains(TINT_COLOR_CONTROL_NORMAL, resId)) { 141469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colorAttr = R.attr.colorControlNormal; 142469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colorAttrSet = true; 143469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } else if (arrayContains(TINT_COLOR_CONTROL_ACTIVATED, resId)) { 144469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colorAttr = R.attr.colorControlActivated; 145469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colorAttrSet = true; 146469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } else if (arrayContains(TINT_COLOR_BACKGROUND_MULTIPLY, resId)) { 147469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colorAttr = android.R.attr.colorBackground; 148469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colorAttrSet = true; 149469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes tintMode = PorterDuff.Mode.MULTIPLY; 150469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 151469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 152f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes if (colorAttrSet) { 153469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes if (tintMode == null) { 154469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes tintMode = DEFAULT_MODE; 155469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 156f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes final int color = getThemeAttrColor(colorAttr); 157469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 158469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes // First, lets see if the cache already contains the color filter 159469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes PorterDuffColorFilter filter = COLOR_FILTER_CACHE.get(color, tintMode); 160469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 161469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes if (filter == null) { 162469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes // Cache miss, so create a color filter and add it to the cache 163469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes filter = new PorterDuffColorFilter(color, tintMode); 164469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes COLOR_FILTER_CACHE.put(color, tintMode, filter); 165469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 166469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 167469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes // Finally set the color filter 168469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes drawable.setColorFilter(filter); 169469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 170469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes if (DEBUG) { 171469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes Log.d(TAG, "Tinted Drawable ID: " + mResources.getResourceName(resId) + 172469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes " with color: #" + Integer.toHexString(color)); 173469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 174469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 175469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 176469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 177469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static boolean arrayContains(int[] array, int value) { 178469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes for (int id : array) { 179469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes if (id == value) { 180469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes return true; 181469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 182469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 183469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes return false; 184469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 185469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 186469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private ColorStateList getDefaultColorStateList() { 187469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes if (mDefaultColorStateList == null) { 188469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes /** 189469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * Generate the default color state list which uses the colorControl attributes. 190469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes * Order is important here. The default enabled state needs to go at the bottom. 191469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes */ 192469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 193469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes final int colorControlNormal = getThemeAttrColor(R.attr.colorControlNormal); 194469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes final int colorControlActivated = getThemeAttrColor(R.attr.colorControlActivated); 195469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 196469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes final int[][] states = new int[7][]; 197469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes final int[] colors = new int[7]; 198469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes int i = 0; 199469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 200c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes // Disabled state 201c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes states[i] = new int[] { -android.R.attr.state_enabled }; 202c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes colors[i] = getDisabledThemeAttrColor(R.attr.colorControlNormal); 203469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes i++; 204469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 205c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes states[i] = new int[] { android.R.attr.state_focused }; 206469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colors[i] = colorControlActivated; 207469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes i++; 208469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 209c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes states[i] = new int[] { android.R.attr.state_activated }; 210469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colors[i] = colorControlActivated; 211469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes i++; 212469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 213c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes states[i] = new int[] { android.R.attr.state_pressed }; 214469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colors[i] = colorControlActivated; 215469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes i++; 216469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 217c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes states[i] = new int[] { android.R.attr.state_checked }; 218469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes colors[i] = colorControlActivated; 219469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes i++; 220469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 221c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes states[i] = new int[] { android.R.attr.state_selected }; 222c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes colors[i] = colorControlActivated; 223469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes i++; 224469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 225c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes // Default enabled state 226469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes states[i] = new int[0]; 227c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes colors[i] = colorControlNormal; 228469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes i++; 229469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 230469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes mDefaultColorStateList = new ColorStateList(states, colors); 231469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 232469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes return mDefaultColorStateList; 233469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 234469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 235469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes int getThemeAttrColor(int attr) { 236f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes if (mContext.getTheme().resolveAttribute(attr, mTypedValue, true)) { 237f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes if (mTypedValue.type >= TypedValue.TYPE_FIRST_INT 238f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes && mTypedValue.type <= TypedValue.TYPE_LAST_INT) { 239f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes return mTypedValue.data; 240f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes } else if (mTypedValue.type == TypedValue.TYPE_STRING) { 241f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes return mResources.getColor(mTypedValue.resourceId); 242f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes } 243f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes } 244f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes return 0; 245469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 246469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 247c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes int getDisabledThemeAttrColor(int attr) { 248f31fb9d2fd3b5b130f3f5ac121b033546d869231Chris Banes final int color = getThemeAttrColor(attr); 249c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes final int originalAlpha = Color.alpha(color); 250c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes 251c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes // Now retrieve the disabledAlpha value from the theme 252c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes mContext.getTheme().resolveAttribute(android.R.attr.disabledAlpha, mTypedValue, true); 253c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes final float disabledAlpha = mTypedValue.getFloat(); 254c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes 255c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes // Return the color, multiplying the original alpha by the disabled value 256c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes return (color & 0x00ffffff) | (Math.round(originalAlpha * disabledAlpha) << 24); 257c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes } 258c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes 259469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static class ColorFilterLruCache extends LruCache<Integer, PorterDuffColorFilter> { 260469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 261469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes public ColorFilterLruCache(int maxSize) { 262469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes super(maxSize); 263469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 264469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 265469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes PorterDuffColorFilter get(int color, PorterDuff.Mode mode) { 266469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes return get(generateCacheKey(color, mode)); 267469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 268469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 269469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes PorterDuffColorFilter put(int color, PorterDuff.Mode mode, PorterDuffColorFilter filter) { 270469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes return put(generateCacheKey(color, mode), filter); 271469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 272469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes 273469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes private static int generateCacheKey(int color, PorterDuff.Mode mode) { 274469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes int hashCode = 1; 275469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes hashCode = 31 * hashCode + color; 276469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes hashCode = 31 * hashCode + mode.hashCode(); 277469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes return hashCode; 278469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 279469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes } 280469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes} 281