FloatingActionButtonLollipop.java revision 522c70ab180af24bf9777cec0a1a9b804c77c8d9
19840efe3dbdc7026521da8576574c55120782f6cChris Banes/*
29840efe3dbdc7026521da8576574c55120782f6cChris Banes * Copyright (C) 2015 The Android Open Source Project
39840efe3dbdc7026521da8576574c55120782f6cChris Banes *
49840efe3dbdc7026521da8576574c55120782f6cChris Banes * Licensed under the Apache License, Version 2.0 (the "License");
59840efe3dbdc7026521da8576574c55120782f6cChris Banes * you may not use this file except in compliance with the License.
69840efe3dbdc7026521da8576574c55120782f6cChris Banes * You may obtain a copy of the License at
79840efe3dbdc7026521da8576574c55120782f6cChris Banes *
89840efe3dbdc7026521da8576574c55120782f6cChris Banes *      http://www.apache.org/licenses/LICENSE-2.0
99840efe3dbdc7026521da8576574c55120782f6cChris Banes *
109840efe3dbdc7026521da8576574c55120782f6cChris Banes * Unless required by applicable law or agreed to in writing, software
119840efe3dbdc7026521da8576574c55120782f6cChris Banes * distributed under the License is distributed on an "AS IS" BASIS,
129840efe3dbdc7026521da8576574c55120782f6cChris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139840efe3dbdc7026521da8576574c55120782f6cChris Banes * See the License for the specific language governing permissions and
149840efe3dbdc7026521da8576574c55120782f6cChris Banes * limitations under the License.
159840efe3dbdc7026521da8576574c55120782f6cChris Banes */
169840efe3dbdc7026521da8576574c55120782f6cChris Banes
179840efe3dbdc7026521da8576574c55120782f6cChris Banespackage android.support.design.widget;
189840efe3dbdc7026521da8576574c55120782f6cChris Banes
19f0aec033caa46d2cdddad020b8748d24f921ad5bChris Banesimport android.animation.AnimatorSet;
209840efe3dbdc7026521da8576574c55120782f6cChris Banesimport android.animation.ObjectAnimator;
219840efe3dbdc7026521da8576574c55120782f6cChris Banesimport android.animation.StateListAnimator;
229840efe3dbdc7026521da8576574c55120782f6cChris Banesimport android.content.res.ColorStateList;
239840efe3dbdc7026521da8576574c55120782f6cChris Banesimport android.graphics.PorterDuff;
246d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banesimport android.graphics.Rect;
259840efe3dbdc7026521da8576574c55120782f6cChris Banesimport android.graphics.drawable.Drawable;
261c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banesimport android.graphics.drawable.GradientDrawable;
276d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banesimport android.graphics.drawable.InsetDrawable;
28cd78954a2b32d9c22686f12c194fac7e49566cf6Chris Banesimport android.graphics.drawable.LayerDrawable;
299840efe3dbdc7026521da8576574c55120782f6cChris Banesimport android.graphics.drawable.RippleDrawable;
30829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanuimport android.os.Build;
318f886fe8c7e23fe6ccb8734167c960c2ed3429c3Alan Viveretteimport android.support.annotation.RequiresApi;
327e82b99953680915596eaf0eb35927388e574ca8Chris Banesimport android.support.v4.graphics.drawable.DrawableCompat;
33f0aec033caa46d2cdddad020b8748d24f921ad5bChris Banesimport android.view.View;
349840efe3dbdc7026521da8576574c55120782f6cChris Banes
358f886fe8c7e23fe6ccb8734167c960c2ed3429c3Alan Viverette@RequiresApi(21)
36522c70ab180af24bf9777cec0a1a9b804c77c8d9Aurimas Liutikasclass FloatingActionButtonLollipop extends FloatingActionButtonImpl {
379840efe3dbdc7026521da8576574c55120782f6cChris Banes
386d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes    private InsetDrawable mInsetDrawable;
399840efe3dbdc7026521da8576574c55120782f6cChris Banes
40fc780bab91bd4275ae2c3b75c3dfb327e008e4dbChris Banes    FloatingActionButtonLollipop(VisibilityAwareImageButton view,
41ae7189188acb2bc972b08d9fbd59939f341c7829Aurimas Liutikas            ShadowViewDelegate shadowViewDelegate) {
42ae7189188acb2bc972b08d9fbd59939f341c7829Aurimas Liutikas        super(view, shadowViewDelegate);
439840efe3dbdc7026521da8576574c55120782f6cChris Banes    }
449840efe3dbdc7026521da8576574c55120782f6cChris Banes
459840efe3dbdc7026521da8576574c55120782f6cChris Banes    @Override
46097e80a3c5518c6bf2e9f3f9b55ed9f4b5cc37e8Chris Banes    void setBackgroundDrawable(ColorStateList backgroundTint,
47cd78954a2b32d9c22686f12c194fac7e49566cf6Chris Banes            PorterDuff.Mode backgroundTintMode, int rippleColor, int borderWidth) {
48097e80a3c5518c6bf2e9f3f9b55ed9f4b5cc37e8Chris Banes        // Now we need to tint the shape background with the tint
49097e80a3c5518c6bf2e9f3f9b55ed9f4b5cc37e8Chris Banes        mShapeDrawable = DrawableCompat.wrap(createShapeDrawable());
507e82b99953680915596eaf0eb35927388e574ca8Chris Banes        DrawableCompat.setTintList(mShapeDrawable, backgroundTint);
519840efe3dbdc7026521da8576574c55120782f6cChris Banes        if (backgroundTintMode != null) {
527e82b99953680915596eaf0eb35927388e574ca8Chris Banes            DrawableCompat.setTintMode(mShapeDrawable, backgroundTintMode);
539840efe3dbdc7026521da8576574c55120782f6cChris Banes        }
549840efe3dbdc7026521da8576574c55120782f6cChris Banes
55cd78954a2b32d9c22686f12c194fac7e49566cf6Chris Banes        final Drawable rippleContent;
56cd78954a2b32d9c22686f12c194fac7e49566cf6Chris Banes        if (borderWidth > 0) {
5780de0674c28a2bd9ade11f24a3b0e46ea83b6847Chris Banes            mBorderDrawable = createBorderDrawable(borderWidth, backgroundTint);
5880de0674c28a2bd9ade11f24a3b0e46ea83b6847Chris Banes            rippleContent = new LayerDrawable(new Drawable[]{mBorderDrawable, mShapeDrawable});
59cd78954a2b32d9c22686f12c194fac7e49566cf6Chris Banes        } else {
60cd78954a2b32d9c22686f12c194fac7e49566cf6Chris Banes            mBorderDrawable = null;
61cd78954a2b32d9c22686f12c194fac7e49566cf6Chris Banes            rippleContent = mShapeDrawable;
62cd78954a2b32d9c22686f12c194fac7e49566cf6Chris Banes        }
63cd78954a2b32d9c22686f12c194fac7e49566cf6Chris Banes
649840efe3dbdc7026521da8576574c55120782f6cChris Banes        mRippleDrawable = new RippleDrawable(ColorStateList.valueOf(rippleColor),
65cd78954a2b32d9c22686f12c194fac7e49566cf6Chris Banes                rippleContent, null);
669840efe3dbdc7026521da8576574c55120782f6cChris Banes
673d81c900316412b4130bf40e0dd8b0d3d3a93e78Chris Banes        mContentBackground = mRippleDrawable;
683d81c900316412b4130bf40e0dd8b0d3d3a93e78Chris Banes
699840efe3dbdc7026521da8576574c55120782f6cChris Banes        mShadowViewDelegate.setBackgroundDrawable(mRippleDrawable);
709840efe3dbdc7026521da8576574c55120782f6cChris Banes    }
719840efe3dbdc7026521da8576574c55120782f6cChris Banes
729840efe3dbdc7026521da8576574c55120782f6cChris Banes    @Override
739840efe3dbdc7026521da8576574c55120782f6cChris Banes    void setRippleColor(int rippleColor) {
748603357c9433b9aef1805413a3bfc4a4f8decc50Chris Banes        if (mRippleDrawable instanceof RippleDrawable) {
758603357c9433b9aef1805413a3bfc4a4f8decc50Chris Banes            ((RippleDrawable) mRippleDrawable).setColor(ColorStateList.valueOf(rippleColor));
768603357c9433b9aef1805413a3bfc4a4f8decc50Chris Banes        } else {
778603357c9433b9aef1805413a3bfc4a4f8decc50Chris Banes            super.setRippleColor(rippleColor);
788603357c9433b9aef1805413a3bfc4a4f8decc50Chris Banes        }
799840efe3dbdc7026521da8576574c55120782f6cChris Banes    }
809840efe3dbdc7026521da8576574c55120782f6cChris Banes
819840efe3dbdc7026521da8576574c55120782f6cChris Banes    @Override
82f0aec033caa46d2cdddad020b8748d24f921ad5bChris Banes    void onElevationsChanged(final float elevation, final float pressedTranslationZ) {
83829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu        final int sdk = Build.VERSION.SDK_INT;
84829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu        if (sdk == 21) {
85829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            // Animations produce NPE in version 21. Bluntly set the values instead (matching the
86829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            // logic in the animations below).
87829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            if (mView.isEnabled()) {
88829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                mView.setElevation(elevation);
89829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                if (mView.isFocused() || mView.isPressed()) {
90829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                    mView.setTranslationZ(pressedTranslationZ);
91829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                } else {
92829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                    mView.setTranslationZ(0);
93829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                }
94829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            } else {
95829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                mView.setElevation(0);
96829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                mView.setTranslationZ(0);
97829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            }
98829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu        } else {
99829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            final StateListAnimator stateListAnimator = new StateListAnimator();
100829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu
101829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            // Animate elevation and translationZ to our values when pressed
102829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            AnimatorSet set = new AnimatorSet();
103829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            set.play(ObjectAnimator.ofFloat(mView, "elevation", elevation).setDuration(0))
104829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                    .with(ObjectAnimator.ofFloat(mView, View.TRANSLATION_Z, pressedTranslationZ)
105829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                            .setDuration(PRESSED_ANIM_DURATION));
106829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            set.setInterpolator(ANIM_INTERPOLATOR);
107829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            stateListAnimator.addState(PRESSED_ENABLED_STATE_SET, set);
108829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu
109829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            // Same deal for when we're focused
110829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            set = new AnimatorSet();
111829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            set.play(ObjectAnimator.ofFloat(mView, "elevation", elevation).setDuration(0))
112829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                    .with(ObjectAnimator.ofFloat(mView, View.TRANSLATION_Z, pressedTranslationZ)
113829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                            .setDuration(PRESSED_ANIM_DURATION));
114829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            set.setInterpolator(ANIM_INTERPOLATOR);
115829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            stateListAnimator.addState(FOCUSED_ENABLED_STATE_SET, set);
116829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu
117829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            // Animate translationZ to 0 if not pressed
118829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            set = new AnimatorSet();
119829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            set.playSequentially(
120829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                    ObjectAnimator.ofFloat(mView, "elevation", elevation).setDuration(0),
121829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                    // This is a no-op animation which exists here only for introducing the duration
122829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                    // because setting the delay (on the next animation) via "setDelay" or "after"
123829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                    // can trigger a NPE between android versions 22 and 24 (due to a framework
124829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                    // bug). The issue has been fixed in version 25.
125829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                    ObjectAnimator.ofFloat(mView, View.TRANSLATION_Z, mView.getTranslationZ())
126829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                            .setDuration(PRESSED_ANIM_DELAY),
127829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                    ObjectAnimator.ofFloat(mView, View.TRANSLATION_Z, 0f)
128829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                            .setDuration(PRESSED_ANIM_DURATION));
129829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            set.setInterpolator(ANIM_INTERPOLATOR);
130829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            stateListAnimator.addState(ENABLED_STATE_SET, set);
131829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu
132829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            // Animate everything to 0 when disabled
133829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            set = new AnimatorSet();
134829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            set.play(ObjectAnimator.ofFloat(mView, "elevation", 0f).setDuration(0))
135829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu                    .with(ObjectAnimator.ofFloat(mView, View.TRANSLATION_Z, 0f).setDuration(0));
136829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            set.setInterpolator(ANIM_INTERPOLATOR);
137829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            stateListAnimator.addState(EMPTY_STATE_SET, set);
138829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu
139829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu            mView.setStateListAnimator(stateListAnimator);
140829c95c8a3fd508b798bedff028d7d6b55e16ce5Andrei Stingaceanu        }
1416d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes
1426d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes        if (mShadowViewDelegate.isCompatPaddingEnabled()) {
1436d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes            updatePadding();
1446d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes        }
1456d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes    }
1466d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes
1476d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes    @Override
1486d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes    public float getElevation() {
1496d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes        return mView.getElevation();
1506d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes    }
1516d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes
1526d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes    @Override
1536d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes    void onCompatShadowChanged() {
1546d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes        updatePadding();
1556d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes    }
1566d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes
1576d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes    @Override
1586d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes    void onPaddingUpdated(Rect padding) {
1596d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes        if (mShadowViewDelegate.isCompatPaddingEnabled()) {
1606d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes            mInsetDrawable = new InsetDrawable(mRippleDrawable,
1616d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes                    padding.left, padding.top, padding.right, padding.bottom);
1626d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes            mShadowViewDelegate.setBackgroundDrawable(mInsetDrawable);
1636d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes        } else {
1646d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes            mShadowViewDelegate.setBackgroundDrawable(mRippleDrawable);
1656d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes        }
1669840efe3dbdc7026521da8576574c55120782f6cChris Banes    }
1679840efe3dbdc7026521da8576574c55120782f6cChris Banes
1689840efe3dbdc7026521da8576574c55120782f6cChris Banes    @Override
1699840efe3dbdc7026521da8576574c55120782f6cChris Banes    void onDrawableStateChanged(int[] state) {
1709840efe3dbdc7026521da8576574c55120782f6cChris Banes        // no-op
1719840efe3dbdc7026521da8576574c55120782f6cChris Banes    }
1729840efe3dbdc7026521da8576574c55120782f6cChris Banes
1739840efe3dbdc7026521da8576574c55120782f6cChris Banes    @Override
1749840efe3dbdc7026521da8576574c55120782f6cChris Banes    void jumpDrawableToCurrentState() {
1759840efe3dbdc7026521da8576574c55120782f6cChris Banes        // no-op
1769840efe3dbdc7026521da8576574c55120782f6cChris Banes    }
1779840efe3dbdc7026521da8576574c55120782f6cChris Banes
178d9770e12c8ff2d4417700492c6616572be897e93Chris Banes    @Override
179d9770e12c8ff2d4417700492c6616572be897e93Chris Banes    boolean requirePreDrawListener() {
180d9770e12c8ff2d4417700492c6616572be897e93Chris Banes        return false;
181d9770e12c8ff2d4417700492c6616572be897e93Chris Banes    }
182d9770e12c8ff2d4417700492c6616572be897e93Chris Banes
18380de0674c28a2bd9ade11f24a3b0e46ea83b6847Chris Banes    @Override
18480de0674c28a2bd9ade11f24a3b0e46ea83b6847Chris Banes    CircularBorderDrawable newCircularDrawable() {
18580de0674c28a2bd9ade11f24a3b0e46ea83b6847Chris Banes        return new CircularBorderDrawableLollipop();
18680de0674c28a2bd9ade11f24a3b0e46ea83b6847Chris Banes    }
1876d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes
18815375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
1891c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes    GradientDrawable newGradientDrawableForShape() {
1901c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes        return new AlwaysStatefulGradientDrawable();
1911c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes    }
1921c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes
1931c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes    @Override
1946d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes    void getPadding(Rect rect) {
1956d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes        if (mShadowViewDelegate.isCompatPaddingEnabled()) {
1966d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes            final float radius = mShadowViewDelegate.getRadius();
1976d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes            final float maxShadowSize = getElevation() + mPressedTranslationZ;
1986d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes            final int hPadding = (int) Math.ceil(
1996d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes                    ShadowDrawableWrapper.calculateHorizontalPadding(maxShadowSize, radius, false));
2006d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes            final int vPadding = (int) Math.ceil(
2016d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes                    ShadowDrawableWrapper.calculateVerticalPadding(maxShadowSize, radius, false));
2026d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes            rect.set(hPadding, vPadding, hPadding, vPadding);
2036d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes        } else {
2046d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes            rect.set(0, 0, 0, 0);
2056d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes        }
2066d7a9a02765e4cb497081e66dafb5d9fa76f4312Chris Banes    }
2071c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes
2081c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes    /**
2091c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes     * LayerDrawable on L+ caches its isStateful() state and doesn't refresh it,
2101c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes     * meaning that if we apply a tint to one of its children, the parent doesn't become
2111c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes     * stateful and the tint doesn't work for state changes. We workaround it by saying that we
2121c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes     * are always stateful. If we don't have a stateful tint, the change is ignored anyway.
2131c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes     */
2141c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes    static class AlwaysStatefulGradientDrawable extends GradientDrawable {
2151c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes        @Override
2161c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes        public boolean isStateful() {
2171c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes            return true;
2181c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes        }
2191c4d0c9dec028624cd661be53e68b1464b14ab7fChris Banes    }
220124d52000d70f3a0ef64b1c70b72238441cbf0edDeepanshu Gupta}
221