111417b1cfde8f1749905f2d735623af9214148afJeff Brown/*
211417b1cfde8f1749905f2d735623af9214148afJeff Brown * Copyright (C) 2013 The Android Open Source Project
311417b1cfde8f1749905f2d735623af9214148afJeff Brown *
411417b1cfde8f1749905f2d735623af9214148afJeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
511417b1cfde8f1749905f2d735623af9214148afJeff Brown * you may not use this file except in compliance with the License.
611417b1cfde8f1749905f2d735623af9214148afJeff Brown * You may obtain a copy of the License at
711417b1cfde8f1749905f2d735623af9214148afJeff Brown *
811417b1cfde8f1749905f2d735623af9214148afJeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
911417b1cfde8f1749905f2d735623af9214148afJeff Brown *
1011417b1cfde8f1749905f2d735623af9214148afJeff Brown * Unless required by applicable law or agreed to in writing, software
1111417b1cfde8f1749905f2d735623af9214148afJeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
1211417b1cfde8f1749905f2d735623af9214148afJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1311417b1cfde8f1749905f2d735623af9214148afJeff Brown * See the License for the specific language governing permissions and
1411417b1cfde8f1749905f2d735623af9214148afJeff Brown * limitations under the License.
1511417b1cfde8f1749905f2d735623af9214148afJeff Brown */
1611417b1cfde8f1749905f2d735623af9214148afJeff Brown
1711417b1cfde8f1749905f2d735623af9214148afJeff Brownpackage android.support.v4.graphics.drawable;
1811417b1cfde8f1749905f2d735623af9214148afJeff Brown
19469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.content.res.ColorStateList;
20ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhuimport android.content.res.Resources;
21ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhuimport android.graphics.ColorFilter;
22469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banesimport android.graphics.PorterDuff;
2311417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.graphics.drawable.Drawable;
24b3631128a65374bd3aee50542cec9dfe40dbcc8aChris Banesimport android.support.annotation.ColorInt;
25b3631128a65374bd3aee50542cec9dfe40dbcc8aChris Banesimport android.support.annotation.NonNull;
26b3631128a65374bd3aee50542cec9dfe40dbcc8aChris Banesimport android.support.annotation.Nullable;
27621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liuimport android.support.v4.view.ViewCompat;
28ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhuimport android.util.AttributeSet;
29ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhuimport org.xmlpull.v1.XmlPullParser;
30ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhuimport org.xmlpull.v1.XmlPullParserException;
31ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu
32ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhuimport java.io.IOException;
3311417b1cfde8f1749905f2d735623af9214148afJeff Brown
3411417b1cfde8f1749905f2d735623af9214148afJeff Brown/**
3511417b1cfde8f1749905f2d735623af9214148afJeff Brown * Helper for accessing features in {@link android.graphics.drawable.Drawable}
3611417b1cfde8f1749905f2d735623af9214148afJeff Brown * introduced after API level 4 in a backwards compatible fashion.
3711417b1cfde8f1749905f2d735623af9214148afJeff Brown */
38c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banespublic final class DrawableCompat {
3911417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
4011417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Interface for the full API.
4111417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
4211417b1cfde8f1749905f2d735623af9214148afJeff Brown    interface DrawableImpl {
4311417b1cfde8f1749905f2d735623af9214148afJeff Brown        void jumpToCurrentState(Drawable drawable);
445df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette        void setAutoMirrored(Drawable drawable, boolean mirrored);
455df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette        boolean isAutoMirrored(Drawable drawable);
4649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        void setHotspot(Drawable drawable, float x, float y);
47ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        void setHotspotBounds(Drawable drawable, int left, int top, int right, int bottom);
48469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        void setTint(Drawable drawable, int tint);
49469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        void setTintList(Drawable drawable, ColorStateList tint);
50469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        void setTintMode(Drawable drawable, PorterDuff.Mode tintMode);
517e82b99953680915596eaf0eb35927388e574ca8Chris Banes        Drawable wrap(Drawable drawable);
522118c89bff1334815e82f89c4fdc9572d0a04c52Alan Viverette        boolean setLayoutDirection(Drawable drawable, int layoutDirection);
53621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        int getLayoutDirection(Drawable drawable);
54ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        int getAlpha(Drawable drawable);
55ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        void applyTheme(Drawable drawable, Resources.Theme t);
56ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        boolean canApplyTheme(Drawable drawable);
57ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        ColorFilter getColorFilter(Drawable drawable);
582aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes        void clearColorFilter(Drawable drawable);
59ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        void inflate(Drawable drawable, Resources res, XmlPullParser parser, AttributeSet attrs,
60ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu                     Resources.Theme t) throws IOException, XmlPullParserException;
6111417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
6211417b1cfde8f1749905f2d735623af9214148afJeff Brown
6311417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
6411417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Interface implementation that doesn't use anything about v4 APIs.
6511417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
6611417b1cfde8f1749905f2d735623af9214148afJeff Brown    static class BaseDrawableImpl implements DrawableImpl {
6711417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
6811417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void jumpToCurrentState(Drawable drawable) {
6911417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
705df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette
715df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette        @Override
725df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette        public void setAutoMirrored(Drawable drawable, boolean mirrored) {
735df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette        }
745df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette
755df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette        @Override
765df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette        public boolean isAutoMirrored(Drawable drawable) {
775df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette            return false;
785df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette        }
7949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
8049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        @Override
8149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        public void setHotspot(Drawable drawable, float x, float y) {
8249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
83ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes
84ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        @Override
85ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        public void setHotspotBounds(Drawable drawable, int left, int top, int right, int bottom) {
86ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        }
87469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes
88469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        @Override
89469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        public void setTint(Drawable drawable, int tint) {
907e82b99953680915596eaf0eb35927388e574ca8Chris Banes            DrawableCompatBase.setTint(drawable, tint);
91469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        }
92469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes
93469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        @Override
94469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        public void setTintList(Drawable drawable, ColorStateList tint) {
957e82b99953680915596eaf0eb35927388e574ca8Chris Banes            DrawableCompatBase.setTintList(drawable, tint);
96469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        }
97469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes
98469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        @Override
99469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        public void setTintMode(Drawable drawable, PorterDuff.Mode tintMode) {
1007e82b99953680915596eaf0eb35927388e574ca8Chris Banes            DrawableCompatBase.setTintMode(drawable, tintMode);
1017e82b99953680915596eaf0eb35927388e574ca8Chris Banes        }
1027e82b99953680915596eaf0eb35927388e574ca8Chris Banes
1037e82b99953680915596eaf0eb35927388e574ca8Chris Banes        @Override
1047e82b99953680915596eaf0eb35927388e574ca8Chris Banes        public Drawable wrap(Drawable drawable) {
1057e82b99953680915596eaf0eb35927388e574ca8Chris Banes            return DrawableCompatBase.wrapForTinting(drawable);
106469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        }
107621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu
108621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        @Override
1092118c89bff1334815e82f89c4fdc9572d0a04c52Alan Viverette        public boolean setLayoutDirection(Drawable drawable, int layoutDirection) {
110621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            // No op for API < 23
1112118c89bff1334815e82f89c4fdc9572d0a04c52Alan Viverette            return false;
112621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        }
113621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu
114621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        @Override
115621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        public int getLayoutDirection(Drawable drawable) {
116621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            return ViewCompat.LAYOUT_DIRECTION_LTR;
117621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        }
118ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu
119ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        @Override
120ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        public int getAlpha(Drawable drawable) {
121ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            return 0;
122ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        }
123ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu
124ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        @Override
125ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        public void applyTheme(Drawable drawable, Resources.Theme t) {
126ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        }
127ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu
128ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        @Override
129ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        public boolean canApplyTheme(Drawable drawable) {
130ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            return false;
131ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        }
132ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu
133ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        @Override
134ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        public ColorFilter getColorFilter(Drawable drawable) {
135ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            return null;
136ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        }
137ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu
138ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        @Override
1392aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes        public void clearColorFilter(Drawable drawable) {
1402aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes            drawable.clearColorFilter();
1412aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes        }
1422aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes
1432aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes        @Override
144ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        public void inflate(Drawable drawable, Resources res, XmlPullParser parser,
145ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu                            AttributeSet attrs, Resources.Theme t)
146ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu                throws IOException, XmlPullParserException {
147ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompatBase.inflate(drawable, res, parser, attrs, t);
148ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        }
14911417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
15011417b1cfde8f1749905f2d735623af9214148afJeff Brown
15111417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
15211417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Interface implementation for devices with at least v11 APIs.
15311417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
154f185f104c4786740765e549d535f9ba1052f96ccKirill Grouchnikov    static class HoneycombDrawableImpl extends BaseDrawableImpl {
15511417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
15611417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void jumpToCurrentState(Drawable drawable) {
15711417b1cfde8f1749905f2d735623af9214148afJeff Brown            DrawableCompatHoneycomb.jumpToCurrentState(drawable);
15811417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
1597e82b99953680915596eaf0eb35927388e574ca8Chris Banes
1607e82b99953680915596eaf0eb35927388e574ca8Chris Banes        @Override
1617e82b99953680915596eaf0eb35927388e574ca8Chris Banes        public Drawable wrap(Drawable drawable) {
1627e82b99953680915596eaf0eb35927388e574ca8Chris Banes            return DrawableCompatHoneycomb.wrapForTinting(drawable);
1637e82b99953680915596eaf0eb35927388e574ca8Chris Banes        }
16411417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
16511417b1cfde8f1749905f2d735623af9214148afJeff Brown
166b01b01dddd64c945dd8dfa896648aa36dc47dde3Chris Banes    static class JellybeanMr1DrawableImpl extends HoneycombDrawableImpl {
167b01b01dddd64c945dd8dfa896648aa36dc47dde3Chris Banes        @Override
1682118c89bff1334815e82f89c4fdc9572d0a04c52Alan Viverette        public boolean setLayoutDirection(Drawable drawable, int layoutDirection) {
1692118c89bff1334815e82f89c4fdc9572d0a04c52Alan Viverette            return DrawableCompatJellybeanMr1.setLayoutDirection(drawable, layoutDirection);
170b01b01dddd64c945dd8dfa896648aa36dc47dde3Chris Banes        }
171b01b01dddd64c945dd8dfa896648aa36dc47dde3Chris Banes
172b01b01dddd64c945dd8dfa896648aa36dc47dde3Chris Banes        @Override
173b01b01dddd64c945dd8dfa896648aa36dc47dde3Chris Banes        public int getLayoutDirection(Drawable drawable) {
174b01b01dddd64c945dd8dfa896648aa36dc47dde3Chris Banes            final int dir = DrawableCompatJellybeanMr1.getLayoutDirection(drawable);
1752087fbca6c7b0c203e9970d5e229f66fab3ebacaChris Banes            return dir >= 0 ? dir : ViewCompat.LAYOUT_DIRECTION_LTR;
176b01b01dddd64c945dd8dfa896648aa36dc47dde3Chris Banes        }
177b01b01dddd64c945dd8dfa896648aa36dc47dde3Chris Banes    }
178b01b01dddd64c945dd8dfa896648aa36dc47dde3Chris Banes
17911417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
18049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Interface implementation for devices with at least KitKat APIs.
1815df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     */
182b01b01dddd64c945dd8dfa896648aa36dc47dde3Chris Banes    static class KitKatDrawableImpl extends JellybeanMr1DrawableImpl {
1835df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette        @Override
1845df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette        public void setAutoMirrored(Drawable drawable, boolean mirrored) {
1855df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette            DrawableCompatKitKat.setAutoMirrored(drawable, mirrored);
1865df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette        }
1875df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette
1885df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette        @Override
1895df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette        public boolean isAutoMirrored(Drawable drawable) {
1905df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette            return DrawableCompatKitKat.isAutoMirrored(drawable);
1915df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette        }
1927e82b99953680915596eaf0eb35927388e574ca8Chris Banes
1937e82b99953680915596eaf0eb35927388e574ca8Chris Banes        @Override
1947e82b99953680915596eaf0eb35927388e574ca8Chris Banes        public Drawable wrap(Drawable drawable) {
1957e82b99953680915596eaf0eb35927388e574ca8Chris Banes            return DrawableCompatKitKat.wrapForTinting(drawable);
1967e82b99953680915596eaf0eb35927388e574ca8Chris Banes        }
197ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu
198ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        @Override
199ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        public int getAlpha(Drawable drawable) {
200ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            return DrawableCompatKitKat.getAlpha(drawable);
201ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        }
2025df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette    }
2035df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette
2045df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette    /**
20549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Interface implementation for devices with at least L APIs.
20649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     */
2077e82b99953680915596eaf0eb35927388e574ca8Chris Banes    static class LollipopDrawableImpl extends KitKatDrawableImpl {
20849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        @Override
20949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        public void setHotspot(Drawable drawable, float x, float y) {
2107e82b99953680915596eaf0eb35927388e574ca8Chris Banes            DrawableCompatLollipop.setHotspot(drawable, x, y);
21149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
212ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes
213ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        @Override
214ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        public void setHotspotBounds(Drawable drawable, int left, int top, int right, int bottom) {
2157e82b99953680915596eaf0eb35927388e574ca8Chris Banes            DrawableCompatLollipop.setHotspotBounds(drawable, left, top, right, bottom);
216ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        }
217469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes
218469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        @Override
219469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        public void setTint(Drawable drawable, int tint) {
2207e82b99953680915596eaf0eb35927388e574ca8Chris Banes            DrawableCompatLollipop.setTint(drawable, tint);
221469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        }
222469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes
223469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        @Override
224469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        public void setTintList(Drawable drawable, ColorStateList tint) {
2257e82b99953680915596eaf0eb35927388e574ca8Chris Banes            DrawableCompatLollipop.setTintList(drawable, tint);
226469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        }
227469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes
228469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        @Override
229469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        public void setTintMode(Drawable drawable, PorterDuff.Mode tintMode) {
2307e82b99953680915596eaf0eb35927388e574ca8Chris Banes            DrawableCompatLollipop.setTintMode(drawable, tintMode);
2317e82b99953680915596eaf0eb35927388e574ca8Chris Banes        }
2327e82b99953680915596eaf0eb35927388e574ca8Chris Banes
2337e82b99953680915596eaf0eb35927388e574ca8Chris Banes        @Override
2347e82b99953680915596eaf0eb35927388e574ca8Chris Banes        public Drawable wrap(Drawable drawable) {
2357e82b99953680915596eaf0eb35927388e574ca8Chris Banes            return DrawableCompatLollipop.wrapForTinting(drawable);
2367e82b99953680915596eaf0eb35927388e574ca8Chris Banes        }
237ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu
238ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        @Override
239ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        public void applyTheme(Drawable drawable, Resources.Theme t) {
240ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompatLollipop.applyTheme(drawable, t);
241ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        }
242ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu
243ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        @Override
244ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        public boolean canApplyTheme(Drawable drawable) {
245ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            return DrawableCompatLollipop.canApplyTheme(drawable);
246ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        }
247ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu
248ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        @Override
249ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        public ColorFilter getColorFilter(Drawable drawable) {
250ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            return DrawableCompatLollipop.getColorFilter(drawable);
251ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        }
252ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu
253ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        @Override
2542aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes        public void clearColorFilter(Drawable drawable) {
2552aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes            DrawableCompatLollipop.clearColorFilter(drawable);
2562aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes        }
2572aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes
2582aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes        @Override
259ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        public void inflate(Drawable drawable, Resources res, XmlPullParser parser,
260ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu                            AttributeSet attrs, Resources.Theme t)
261ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu                throws IOException, XmlPullParserException {
262ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompatLollipop.inflate(drawable, res, parser, attrs, t);
263ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        }
2647e82b99953680915596eaf0eb35927388e574ca8Chris Banes    }
2657e82b99953680915596eaf0eb35927388e574ca8Chris Banes
2667e82b99953680915596eaf0eb35927388e574ca8Chris Banes    /**
267621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * Interface implementation for devices with at least M APIs.
268621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     */
2699925d4a53e0dbaacf07901fb48907fe1aff9bbbdChris Banes    static class MDrawableImpl extends LollipopDrawableImpl {
270621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        @Override
2712118c89bff1334815e82f89c4fdc9572d0a04c52Alan Viverette        public boolean setLayoutDirection(Drawable drawable, int layoutDirection) {
2722118c89bff1334815e82f89c4fdc9572d0a04c52Alan Viverette            return DrawableCompatApi23.setLayoutDirection(drawable, layoutDirection);
273621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        }
274621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu
275621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        @Override
276621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        public int getLayoutDirection(Drawable drawable) {
277621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            return DrawableCompatApi23.getLayoutDirection(drawable);
278621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        }
2799925d4a53e0dbaacf07901fb48907fe1aff9bbbdChris Banes
2809925d4a53e0dbaacf07901fb48907fe1aff9bbbdChris Banes        @Override
2819925d4a53e0dbaacf07901fb48907fe1aff9bbbdChris Banes        public Drawable wrap(Drawable drawable) {
2829925d4a53e0dbaacf07901fb48907fe1aff9bbbdChris Banes            // No need to wrap on M+
2839925d4a53e0dbaacf07901fb48907fe1aff9bbbdChris Banes            return drawable;
2849925d4a53e0dbaacf07901fb48907fe1aff9bbbdChris Banes        }
2852aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes
2862aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes        @Override
2872aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes        public void clearColorFilter(Drawable drawable) {
2882aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes            // We can use clearColorFilter() safely on M+
2892aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes            drawable.clearColorFilter();
2902aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes        }
291621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    }
292621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu
293621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    /**
29411417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Select the correct implementation to use for the current platform.
29511417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
29611417b1cfde8f1749905f2d735623af9214148afJeff Brown    static final DrawableImpl IMPL;
29711417b1cfde8f1749905f2d735623af9214148afJeff Brown    static {
29811417b1cfde8f1749905f2d735623af9214148afJeff Brown        final int version = android.os.Build.VERSION.SDK_INT;
299621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        if (version >= 23) {
300621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            IMPL = new MDrawableImpl();
3017e82b99953680915596eaf0eb35927388e574ca8Chris Banes        } else if (version >= 21) {
3027e82b99953680915596eaf0eb35927388e574ca8Chris Banes            IMPL = new LollipopDrawableImpl();
30349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        } else if (version >= 19) {
3045df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette            IMPL = new KitKatDrawableImpl();
305b01b01dddd64c945dd8dfa896648aa36dc47dde3Chris Banes        } else if (version >= 17) {
306b01b01dddd64c945dd8dfa896648aa36dc47dde3Chris Banes            IMPL = new JellybeanMr1DrawableImpl();
3075df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette        } else if (version >= 11) {
30811417b1cfde8f1749905f2d735623af9214148afJeff Brown            IMPL = new HoneycombDrawableImpl();
30911417b1cfde8f1749905f2d735623af9214148afJeff Brown        } else {
31011417b1cfde8f1749905f2d735623af9214148afJeff Brown            IMPL = new BaseDrawableImpl();
31111417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
31211417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
31311417b1cfde8f1749905f2d735623af9214148afJeff Brown
31411417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
31511417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}.
3165df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * <p>
3175df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * If running on a pre-{@link android.os.Build.VERSION_CODES#HONEYCOMB}
3185df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * device this method does nothing.
3195df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     *
3205df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * @param drawable The Drawable against which to invoke the method.
32111417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
322b3631128a65374bd3aee50542cec9dfe40dbcc8aChris Banes    public static void jumpToCurrentState(@NonNull Drawable drawable) {
32311417b1cfde8f1749905f2d735623af9214148afJeff Brown        IMPL.jumpToCurrentState(drawable);
32411417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
3255df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette
3265df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette    /**
3275df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * Set whether this Drawable is automatically mirrored when its layout
3285df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * direction is RTL (right-to left). See
3295df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * {@link android.util.LayoutDirection}.
3305df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * <p>
3315df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * If running on a pre-{@link android.os.Build.VERSION_CODES#KITKAT} device
3325df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * this method does nothing.
3335df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     *
3345df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * @param drawable The Drawable against which to invoke the method.
3355df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * @param mirrored Set to true if the Drawable should be mirrored, false if
3365df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     *            not.
3375df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     */
338b3631128a65374bd3aee50542cec9dfe40dbcc8aChris Banes    public static void setAutoMirrored(@NonNull Drawable drawable, boolean mirrored) {
3395df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette        IMPL.setAutoMirrored(drawable, mirrored);
3405df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette    }
3415df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette
3425df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette    /**
3435df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * Tells if this Drawable will be automatically mirrored when its layout
3445df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * direction is RTL right-to-left. See {@link android.util.LayoutDirection}.
3455df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * <p>
3465df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * If running on a pre-{@link android.os.Build.VERSION_CODES#KITKAT} device
3475df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * this method returns false.
3485df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     *
3495df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * @param drawable The Drawable against which to invoke the method.
3505df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     * @return boolean Returns true if this Drawable will be automatically
3515df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     *         mirrored.
3525df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette     */
353b3631128a65374bd3aee50542cec9dfe40dbcc8aChris Banes    public static boolean isAutoMirrored(@NonNull Drawable drawable) {
3545df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette        return IMPL.isAutoMirrored(drawable);
3555df122f8bb619edcdbef94cd455efef0e6e44377Alan Viverette    }
35649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
35749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /**
35849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Specifies the hotspot's location within the drawable.
35949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
360ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes     * @param drawable The Drawable against which to invoke the method.
36149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param x The X coordinate of the center of the hotspot
36249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param y The Y coordinate of the center of the hotspot
36349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     */
364b3631128a65374bd3aee50542cec9dfe40dbcc8aChris Banes    public static void setHotspot(@NonNull Drawable drawable, float x, float y) {
36549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        IMPL.setHotspot(drawable, x, y);
36649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
367ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes
368ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes    /**
369ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes     * Sets the bounds to which the hotspot is constrained, if they should be
370ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes     * different from the drawable bounds.
371ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes     *
372ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes     * @param drawable The Drawable against which to invoke the method.
373ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes     */
374b3631128a65374bd3aee50542cec9dfe40dbcc8aChris Banes    public static void setHotspotBounds(@NonNull Drawable drawable, int left, int top,
375ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes            int right, int bottom) {
376ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        IMPL.setHotspotBounds(drawable, left, top, right, bottom);
377ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes    }
378469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes
379469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes    /**
3807b5f76f0cd7c763296aa0b6fbafdd89ba4263e4eChris Banes     * Specifies a tint for {@code drawable}.
381469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes     *
382469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes     * @param drawable The Drawable against which to invoke the method.
3837e82b99953680915596eaf0eb35927388e574ca8Chris Banes     * @param tint     Color to use for tinting this drawable
384469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes     */
385b3631128a65374bd3aee50542cec9dfe40dbcc8aChris Banes    public static void setTint(@NonNull Drawable drawable, @ColorInt int tint) {
386469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        IMPL.setTint(drawable, tint);
387469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes    }
388469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes
389469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes    /**
3907b5f76f0cd7c763296aa0b6fbafdd89ba4263e4eChris Banes     * Specifies a tint for {@code drawable} as a color state list.
391469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes     *
392469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes     * @param drawable The Drawable against which to invoke the method.
3937e82b99953680915596eaf0eb35927388e574ca8Chris Banes     * @param tint     Color state list to use for tinting this drawable, or null to clear the tint
394469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes     */
395b3631128a65374bd3aee50542cec9dfe40dbcc8aChris Banes    public static void setTintList(@NonNull Drawable drawable, @Nullable ColorStateList tint) {
396469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        IMPL.setTintList(drawable, tint);
397469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes    }
398469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes
399469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes    /**
4007b5f76f0cd7c763296aa0b6fbafdd89ba4263e4eChris Banes     * Specifies a tint blending mode for {@code drawable}.
401469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes     *
402469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes     * @param drawable The Drawable against which to invoke the method.
403469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes     * @param tintMode A Porter-Duff blending mode
404469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes     */
405b3631128a65374bd3aee50542cec9dfe40dbcc8aChris Banes    public static void setTintMode(@NonNull Drawable drawable, @Nullable PorterDuff.Mode tintMode) {
406469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes        IMPL.setTintMode(drawable, tintMode);
407469286122bcbbecbdd0bef74fb50f9d8920e77b9Chris Banes    }
4087e82b99953680915596eaf0eb35927388e574ca8Chris Banes
4097e82b99953680915596eaf0eb35927388e574ca8Chris Banes    /**
410ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     * Get the alpha value of the {@code drawable}.
411ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     * 0 means fully transparent, 255 means fully opaque.
412ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     *
413ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     * @param drawable The Drawable against which to invoke the method.
414ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     */
415ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu    public static int getAlpha(@NonNull Drawable drawable) {
416ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        return IMPL.getAlpha(drawable);
417ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu    }
418ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu
419ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu    /**
420ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     * Applies the specified theme to this Drawable and its children.
421ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     */
4222aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes    public static void applyTheme(@NonNull Drawable drawable, @NonNull Resources.Theme t) {
423ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        IMPL.applyTheme(drawable, t);
424ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu    }
425ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu
426ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu    /**
427ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     * Whether a theme can be applied to this Drawable and its children.
428ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     */
4292aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes    public static boolean canApplyTheme(@NonNull Drawable drawable) {
430ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        return IMPL.canApplyTheme(drawable);
431ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu    }
432ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu
433ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu    /**
434ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     * Returns the current color filter, or {@code null} if none set.
435ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     *
436ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     * @return the current color filter, or {@code null} if none set
437ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     */
4382aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes    public static ColorFilter getColorFilter(@NonNull Drawable drawable) {
439ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        return IMPL.getColorFilter(drawable);
440ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu    }
441ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu
442ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu    /**
4432aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes     * Removes the color filter from the given drawable.
4442aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes     */
4452aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes    public static void clearColorFilter(@NonNull Drawable drawable) {
4462aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes        IMPL.clearColorFilter(drawable);
4472aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes    }
4482aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes
4492aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes    /**
450ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     * Inflate this Drawable from an XML resource optionally styled by a theme.
451ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     *
452ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     * @param res Resources used to resolve attribute values
453ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     * @param parser XML parser from which to inflate this Drawable
454ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     * @param attrs Base set of attribute values
455ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     * @param theme Theme to apply, may be null
456ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     * @throws XmlPullParserException
457ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     * @throws IOException
458ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu     */
4592aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes    public static void inflate(@NonNull Drawable drawable, @NonNull Resources res,
4602aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes            @NonNull XmlPullParser parser, @NonNull AttributeSet attrs,
4612aabff2e355c96bf90d6047a613ce0fa2c1ffe45Chris Banes            @Nullable Resources.Theme theme)
462ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            throws XmlPullParserException, IOException {
463ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu        IMPL.inflate(drawable, res, parser, attrs, theme);
464ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu    }
465ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu
466ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu    /**
4677e82b99953680915596eaf0eb35927388e574ca8Chris Banes     * Potentially wrap {@code drawable} so that it may be used for tinting across the
4687e82b99953680915596eaf0eb35927388e574ca8Chris Banes     * different API levels, via the tinting methods in this class.
469be678137d44778590a6220ae0ef13649e83363a9Chris Banes     *
470d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes     * <p>If the given drawable is wrapped, we will copy over certain state over to the wrapped
471d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes     * drawable, such as its bounds, level, visibility and state.</p>
472d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes     *
473be678137d44778590a6220ae0ef13649e83363a9Chris Banes     * <p>You must use the result of this call. If the given drawable is being used by a view
474be678137d44778590a6220ae0ef13649e83363a9Chris Banes     * (as it's background for instance), you must replace the original drawable with
475be678137d44778590a6220ae0ef13649e83363a9Chris Banes     * the result of this call:</p>
476be678137d44778590a6220ae0ef13649e83363a9Chris Banes     *
477be678137d44778590a6220ae0ef13649e83363a9Chris Banes     * <pre>
478be678137d44778590a6220ae0ef13649e83363a9Chris Banes     * Drawable bg = DrawableCompat.wrap(view.getBackground());
479be678137d44778590a6220ae0ef13649e83363a9Chris Banes     * // Need to set the background with the wrapped drawable
480be678137d44778590a6220ae0ef13649e83363a9Chris Banes     * view.setBackground(bg);
481be678137d44778590a6220ae0ef13649e83363a9Chris Banes     *
482be678137d44778590a6220ae0ef13649e83363a9Chris Banes     * // You can now tint the drawable
483be678137d44778590a6220ae0ef13649e83363a9Chris Banes     * DrawableCompat.setTint(bg, ...);
484be678137d44778590a6220ae0ef13649e83363a9Chris Banes     * </pre>
485be678137d44778590a6220ae0ef13649e83363a9Chris Banes     *
486be678137d44778590a6220ae0ef13649e83363a9Chris Banes     * <p>If you need to get hold of the original {@link android.graphics.drawable.Drawable} again,
487be678137d44778590a6220ae0ef13649e83363a9Chris Banes     * you can use the value returned from {@link #unwrap(Drawable)}.</p>
4887e82b99953680915596eaf0eb35927388e574ca8Chris Banes     *
4897e82b99953680915596eaf0eb35927388e574ca8Chris Banes     * @param drawable The Drawable to process
4907e82b99953680915596eaf0eb35927388e574ca8Chris Banes     * @return A drawable capable of being tinted across all API levels.
4917e82b99953680915596eaf0eb35927388e574ca8Chris Banes     *
4927e82b99953680915596eaf0eb35927388e574ca8Chris Banes     * @see #setTint(Drawable, int)
4937e82b99953680915596eaf0eb35927388e574ca8Chris Banes     * @see #setTintList(Drawable, ColorStateList)
4947e82b99953680915596eaf0eb35927388e574ca8Chris Banes     * @see #setTintMode(Drawable, PorterDuff.Mode)
4957e82b99953680915596eaf0eb35927388e574ca8Chris Banes     * @see #unwrap(Drawable)
4967e82b99953680915596eaf0eb35927388e574ca8Chris Banes     */
497b3631128a65374bd3aee50542cec9dfe40dbcc8aChris Banes    public static Drawable wrap(@NonNull Drawable drawable) {
4987e82b99953680915596eaf0eb35927388e574ca8Chris Banes        return IMPL.wrap(drawable);
4997e82b99953680915596eaf0eb35927388e574ca8Chris Banes    }
5007e82b99953680915596eaf0eb35927388e574ca8Chris Banes
5017e82b99953680915596eaf0eb35927388e574ca8Chris Banes    /**
5027e82b99953680915596eaf0eb35927388e574ca8Chris Banes     * Unwrap {@code drawable} if it is the result of a call to {@link #wrap(Drawable)}. If
5037e82b99953680915596eaf0eb35927388e574ca8Chris Banes     * the {@code drawable} is not the result of a call to {@link #wrap(Drawable)} then
5047e82b99953680915596eaf0eb35927388e574ca8Chris Banes     * {@code drawable} is returned as-is.
5057e82b99953680915596eaf0eb35927388e574ca8Chris Banes     *
5067e82b99953680915596eaf0eb35927388e574ca8Chris Banes     * @param drawable The drawable to unwrap
5077e82b99953680915596eaf0eb35927388e574ca8Chris Banes     * @return the unwrapped {@link Drawable} or {@code drawable} if it hasn't been wrapped.
5087e82b99953680915596eaf0eb35927388e574ca8Chris Banes     *
5097e82b99953680915596eaf0eb35927388e574ca8Chris Banes     * @see #wrap(Drawable)
5107e82b99953680915596eaf0eb35927388e574ca8Chris Banes     */
511b3631128a65374bd3aee50542cec9dfe40dbcc8aChris Banes    public static <T extends Drawable> T unwrap(@NonNull Drawable drawable) {
5127e82b99953680915596eaf0eb35927388e574ca8Chris Banes        if (drawable instanceof DrawableWrapper) {
5137e82b99953680915596eaf0eb35927388e574ca8Chris Banes            return (T) ((DrawableWrapper) drawable).getWrappedDrawable();
5147e82b99953680915596eaf0eb35927388e574ca8Chris Banes        }
5157e82b99953680915596eaf0eb35927388e574ca8Chris Banes        return (T) drawable;
5167e82b99953680915596eaf0eb35927388e574ca8Chris Banes    }
517621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu
518621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    /**
519621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * Set the layout direction for this drawable. Should be a resolved
520621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * layout direction, as the Drawable has no capacity to do the resolution on
521621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * its own.
522621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     *
523621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * @param layoutDirection the resolved layout direction for the drawable,
524621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     *                        either {@link ViewCompat#LAYOUT_DIRECTION_LTR}
525621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     *                        or {@link ViewCompat#LAYOUT_DIRECTION_RTL}
5262118c89bff1334815e82f89c4fdc9572d0a04c52Alan Viverette     * @return {@code true} if the layout direction change has caused the
5272118c89bff1334815e82f89c4fdc9572d0a04c52Alan Viverette     *         appearance of the drawable to change such that it needs to be
5282118c89bff1334815e82f89c4fdc9572d0a04c52Alan Viverette     *         re-drawn, {@code false} otherwise
529621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * @see #getLayoutDirection(Drawable)
530621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     */
5312118c89bff1334815e82f89c4fdc9572d0a04c52Alan Viverette    public static boolean setLayoutDirection(@NonNull Drawable drawable, int layoutDirection) {
5322118c89bff1334815e82f89c4fdc9572d0a04c52Alan Viverette        return IMPL.setLayoutDirection(drawable, layoutDirection);
533621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    }
534621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu
535621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    /**
536621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * Returns the resolved layout direction for this Drawable.
537621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     *
538621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * @return One of {@link ViewCompat#LAYOUT_DIRECTION_LTR},
539621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     *         {@link ViewCompat#LAYOUT_DIRECTION_RTL}
540621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * @see #setLayoutDirection(Drawable, int)
541621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     */
542b3631128a65374bd3aee50542cec9dfe40dbcc8aChris Banes    public static int getLayoutDirection(@NonNull Drawable drawable) {
543621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        return IMPL.getLayoutDirection(drawable);
544621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    }
545c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banes
546c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banes    private DrawableCompat() {}
54711417b1cfde8f1749905f2d735623af9214148afJeff Brown}
548