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