1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.settings.widget;
18 
19 
20 import android.content.res.ColorStateList;
21 import android.content.res.Resources;
22 import android.content.res.Resources.Theme;
23 import android.content.res.TypedArray;
24 import android.graphics.drawable.DrawableWrapper;
25 import android.util.AttributeSet;
26 
27 import androidx.annotation.NonNull;
28 import androidx.annotation.Nullable;
29 
30 import com.android.settings.R;
31 
32 import org.xmlpull.v1.XmlPullParser;
33 import org.xmlpull.v1.XmlPullParserException;
34 
35 import java.io.IOException;
36 
37 /**
38  * A Drawable that tints a contained Drawable, overriding the existing tint specified in the
39  * underlying drawable. This class should only be used in XML.
40  *
41  * @attr ref android.R.styleable#DrawableWrapper_drawable
42  * @attr ref R.styleable#TintDrawable_tint
43  */
44 public class TintDrawable extends DrawableWrapper {
45     private ColorStateList mTint;
46     private int[] mThemeAttrs;
47 
48     /** No-arg constructor used by drawable inflation. */
TintDrawable()49     public TintDrawable() {
50         super(null);
51     }
52 
53     @Override
inflate(@onNull Resources r, @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme)54     public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
55             @NonNull AttributeSet attrs, @Nullable Theme theme)
56             throws XmlPullParserException, IOException {
57         final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.TintDrawable);
58 
59         super.inflate(r, parser, attrs, theme);
60 
61         mThemeAttrs = a.extractThemeAttrs();
62         updateStateFromTypedArray(a);
63         a.recycle();
64 
65         applyTint();
66     }
67 
68     @Override
applyTheme(Theme t)69     public void applyTheme(Theme t) {
70         super.applyTheme(t);
71 
72         if (mThemeAttrs != null) {
73             final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.TintDrawable);
74             updateStateFromTypedArray(a);
75             a.recycle();
76         }
77 
78         // Ensure tint is reapplied after applying the theme to ensure this drawables'
79         // tint overrides the underlying drawables' tint.
80         applyTint();
81     }
82 
83     @Override
canApplyTheme()84     public boolean canApplyTheme() {
85         return (mThemeAttrs != null && mThemeAttrs.length > 0) || super.canApplyTheme();
86     }
87 
updateStateFromTypedArray(@onNull TypedArray a)88     private void updateStateFromTypedArray(@NonNull TypedArray a) {
89         if (a.hasValue(R.styleable.TintDrawable_android_drawable)) {
90             setDrawable(a.getDrawable(R.styleable.TintDrawable_android_drawable));
91         }
92         if (a.hasValue(R.styleable.TintDrawable_android_tint)) {
93             mTint = a.getColorStateList(R.styleable.TintDrawable_android_tint);
94         }
95     }
96 
applyTint()97     private void applyTint() {
98         if (getDrawable() != null && mTint != null) {
99             getDrawable().mutate().setTintList(mTint);
100         }
101     }
102 }
103