AppCompatBackgroundHelper.java revision 483ee34ae7ef0cac94d60cbe32a945dae4cb2b21
1091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes/* 2091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * Copyright (C) 2015 The Android Open Source Project 3091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * 4091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * Licensed under the Apache License, Version 2.0 (the "License"); 5091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * you may not use this file except in compliance with the License. 6091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * You may obtain a copy of the License at 7091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * 8091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * http://www.apache.org/licenses/LICENSE-2.0 9091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * 10091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * Unless required by applicable law or agreed to in writing, software 11091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * distributed under the License is distributed on an "AS IS" BASIS, 12091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * See the License for the specific language governing permissions and 14091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes * limitations under the License. 15091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes */ 16091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes 17091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banespackage android.support.v7.widget; 18091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes 19091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.content.res.ColorStateList; 20091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.content.res.TypedArray; 21091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.graphics.PorterDuff; 22091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.graphics.drawable.Drawable; 23483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banesimport android.graphics.drawable.GradientDrawable; 24483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banesimport android.os.Build; 25483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banesimport android.support.annotation.NonNull; 26091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.support.v4.view.ViewCompat; 27091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.support.v7.appcompat.R; 28091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.support.v7.graphics.drawable.DrawableUtils; 29091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.util.AttributeSet; 30091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesimport android.view.View; 31091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes 32091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banesclass AppCompatBackgroundHelper { 33091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes 34091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes private final View mView; 357e4e8b664820f773bc96e37ee1d2bbf500d64e69Chris Banes private final AppCompatDrawableManager mDrawableManager; 36091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes 37091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes private TintInfo mInternalBackgroundTint; 38091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes private TintInfo mBackgroundTint; 39483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes private TintInfo mTmpInfo; 40091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes 417e4e8b664820f773bc96e37ee1d2bbf500d64e69Chris Banes AppCompatBackgroundHelper(View view, AppCompatDrawableManager drawableManager) { 42091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes mView = view; 437e4e8b664820f773bc96e37ee1d2bbf500d64e69Chris Banes mDrawableManager = drawableManager; 44091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 45091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes 46091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes void loadFromAttributes(AttributeSet attrs, int defStyleAttr) { 47091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes TypedArray a = mView.getContext().obtainStyledAttributes(attrs, 48091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes R.styleable.ViewBackgroundHelper, defStyleAttr, 0); 49091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes try { 50091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes if (a.hasValue(R.styleable.ViewBackgroundHelper_android_background)) { 517e4e8b664820f773bc96e37ee1d2bbf500d64e69Chris Banes ColorStateList tint = mDrawableManager.getTintList(mView.getContext(), 52091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes a.getResourceId(R.styleable.ViewBackgroundHelper_android_background, -1)); 53091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes if (tint != null) { 54091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes setInternalBackgroundTint(tint); 55091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 56091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 57091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes if (a.hasValue(R.styleable.ViewBackgroundHelper_backgroundTint)) { 58091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes ViewCompat.setBackgroundTintList(mView, 59091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes a.getColorStateList(R.styleable.ViewBackgroundHelper_backgroundTint)); 60091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 61091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes if (a.hasValue(R.styleable.ViewBackgroundHelper_backgroundTintMode)) { 62091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes ViewCompat.setBackgroundTintMode(mView, 63091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes DrawableUtils.parseTintMode( 64091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes a.getInt(R.styleable.ViewBackgroundHelper_backgroundTintMode, -1), 65091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes null)); 66091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 67091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } finally { 68091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes a.recycle(); 69091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 70091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 71091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes 72091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes void onSetBackgroundResource(int resId) { 73091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes // Update the default background tint 747e4e8b664820f773bc96e37ee1d2bbf500d64e69Chris Banes setInternalBackgroundTint(mDrawableManager != null 757e4e8b664820f773bc96e37ee1d2bbf500d64e69Chris Banes ? mDrawableManager.getTintList(mView.getContext(), resId) 767e4e8b664820f773bc96e37ee1d2bbf500d64e69Chris Banes : null); 77091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 78091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes 79091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes void onSetBackgroundDrawable(Drawable background) { 80091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes // We don't know that this drawable is, so we need to clear the default background tint 81091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes setInternalBackgroundTint(null); 82091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 83091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes 84091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes void setSupportBackgroundTintList(ColorStateList tint) { 85091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes if (mBackgroundTint == null) { 86091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes mBackgroundTint = new TintInfo(); 87091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 88091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes mBackgroundTint.mTintList = tint; 89091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes mBackgroundTint.mHasTintList = true; 90091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes 91091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes applySupportBackgroundTint(); 92091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 93091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes 94091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes ColorStateList getSupportBackgroundTintList() { 95091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes return mBackgroundTint != null ? mBackgroundTint.mTintList : null; 96091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 97091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes 98091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes void setSupportBackgroundTintMode(PorterDuff.Mode tintMode) { 99091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes if (mBackgroundTint == null) { 100091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes mBackgroundTint = new TintInfo(); 101091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 102091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes mBackgroundTint.mTintMode = tintMode; 103091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes mBackgroundTint.mHasTintMode = true; 104091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes 105091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes applySupportBackgroundTint(); 106091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 107091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes 108091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes PorterDuff.Mode getSupportBackgroundTintMode() { 109091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes return mBackgroundTint != null ? mBackgroundTint.mTintMode : null; 110091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 111091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes 112091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes void applySupportBackgroundTint() { 113f7b73431b366b76bcf58536b7b1086489e4683b2Chris Banes final Drawable background = mView.getBackground(); 114f7b73431b366b76bcf58536b7b1086489e4683b2Chris Banes if (background != null) { 115091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes if (mBackgroundTint != null) { 1167e4e8b664820f773bc96e37ee1d2bbf500d64e69Chris Banes AppCompatDrawableManager 1177e4e8b664820f773bc96e37ee1d2bbf500d64e69Chris Banes .tintDrawable(background, mBackgroundTint, mView.getDrawableState()); 118091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } else if (mInternalBackgroundTint != null) { 1197e4e8b664820f773bc96e37ee1d2bbf500d64e69Chris Banes AppCompatDrawableManager.tintDrawable(background, mInternalBackgroundTint, 120f7b73431b366b76bcf58536b7b1086489e4683b2Chris Banes mView.getDrawableState()); 121483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes } else if (shouldCompatTintUsingFrameworkTint(background)) { 122483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes compatTintDrawableUsingFrameworkTint(background); 123091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 124091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 125091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 126091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes 127091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes void setInternalBackgroundTint(ColorStateList tint) { 128091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes if (tint != null) { 129091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes if (mInternalBackgroundTint == null) { 130091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes mInternalBackgroundTint = new TintInfo(); 131091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 132091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes mInternalBackgroundTint.mTintList = tint; 133091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes mInternalBackgroundTint.mHasTintList = true; 134091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } else { 135091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes mInternalBackgroundTint = null; 136091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 137091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes applySupportBackgroundTint(); 138091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes } 139483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes 140483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes private boolean shouldCompatTintUsingFrameworkTint(@NonNull Drawable background) { 141483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes // GradientDrawable doesn't implement setTintList on API 21 142483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes return (Build.VERSION.SDK_INT == 21 && background instanceof GradientDrawable); 143483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes } 144483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes 145483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes private void compatTintDrawableUsingFrameworkTint(@NonNull Drawable background) { 146483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes if (mTmpInfo == null) { 147483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes mTmpInfo = new TintInfo(); 148483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes } 149483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes final TintInfo info = mTmpInfo; 150483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes info.clear(); 151483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes 152483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes final ColorStateList tintList = ViewCompat.getBackgroundTintList(mView); 153483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes if (tintList != null) { 154483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes info.mHasTintList = true; 155483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes info.mTintList = tintList; 156483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes } 157483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes final PorterDuff.Mode mode = ViewCompat.getBackgroundTintMode(mView); 158483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes if (mode != null) { 159483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes info.mHasTintMode = true; 160483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes info.mTintMode = mode; 161483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes } 162483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes 163483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes if (info.mHasTintList || info.mHasTintMode) { 164483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes AppCompatDrawableManager.tintDrawable(background, info, mView.getDrawableState()); 165483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes } 166483ee34ae7ef0cac94d60cbe32a945dae4cb2b21Chris Banes } 167091b0f935e68ce9bfecc2422e60eada33fa3b09cChris Banes} 168