DrawableCompat.java revision 469286122bcbbecbdd0bef74fb50f9d8920e77b9
1/*
2 * Copyright (C) 2013 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
17package android.support.v4.graphics.drawable;
18
19import android.content.res.ColorStateList;
20import android.graphics.PorterDuff;
21import android.graphics.drawable.Drawable;
22import android.os.Build;
23
24/**
25 * Helper for accessing features in {@link android.graphics.drawable.Drawable}
26 * introduced after API level 4 in a backwards compatible fashion.
27 */
28public class DrawableCompat {
29    /**
30     * Interface for the full API.
31     */
32    interface DrawableImpl {
33        void jumpToCurrentState(Drawable drawable);
34        void setAutoMirrored(Drawable drawable, boolean mirrored);
35        boolean isAutoMirrored(Drawable drawable);
36        void setHotspot(Drawable drawable, float x, float y);
37        void setHotspotBounds(Drawable drawable, int left, int top, int right, int bottom);
38        void setTint(Drawable drawable, int tint);
39        void setTintList(Drawable drawable, ColorStateList tint);
40        void setTintMode(Drawable drawable, PorterDuff.Mode tintMode);
41    }
42
43    /**
44     * Interface implementation that doesn't use anything about v4 APIs.
45     */
46    static class BaseDrawableImpl implements DrawableImpl {
47        @Override
48        public void jumpToCurrentState(Drawable drawable) {
49        }
50
51        @Override
52        public void setAutoMirrored(Drawable drawable, boolean mirrored) {
53        }
54
55        @Override
56        public boolean isAutoMirrored(Drawable drawable) {
57            return false;
58        }
59
60        @Override
61        public void setHotspot(Drawable drawable, float x, float y) {
62        }
63
64        @Override
65        public void setHotspotBounds(Drawable drawable, int left, int top, int right, int bottom) {
66        }
67
68        @Override
69        public void setTint(Drawable drawable, int tint) {
70        }
71
72        @Override
73        public void setTintList(Drawable drawable, ColorStateList tint) {
74        }
75
76        @Override
77        public void setTintMode(Drawable drawable, PorterDuff.Mode tintMode) {
78        }
79    }
80
81    /**
82     * Interface implementation for devices with at least v11 APIs.
83     */
84    static class HoneycombDrawableImpl extends BaseDrawableImpl {
85        @Override
86        public void jumpToCurrentState(Drawable drawable) {
87            DrawableCompatHoneycomb.jumpToCurrentState(drawable);
88        }
89    }
90
91    /**
92     * Interface implementation for devices with at least KitKat APIs.
93     */
94    static class KitKatDrawableImpl extends HoneycombDrawableImpl {
95        @Override
96        public void setAutoMirrored(Drawable drawable, boolean mirrored) {
97            DrawableCompatKitKat.setAutoMirrored(drawable, mirrored);
98        }
99
100        @Override
101        public boolean isAutoMirrored(Drawable drawable) {
102            return DrawableCompatKitKat.isAutoMirrored(drawable);
103        }
104    }
105
106    /**
107     * Interface implementation for devices with at least L APIs.
108     */
109    static class LDrawableImpl extends KitKatDrawableImpl {
110        @Override
111        public void setHotspot(Drawable drawable, float x, float y) {
112            DrawableCompatL.setHotspot(drawable, x, y);
113        }
114
115        @Override
116        public void setHotspotBounds(Drawable drawable, int left, int top, int right, int bottom) {
117            DrawableCompatL.setHotspotBounds(drawable, left, top, right, bottom);
118        }
119
120        @Override
121        public void setTint(Drawable drawable, int tint) {
122            DrawableCompatL.setTint(drawable, tint);
123        }
124
125        @Override
126        public void setTintList(Drawable drawable, ColorStateList tint) {
127            DrawableCompatL.setTintList(drawable, tint);
128        }
129
130        @Override
131        public void setTintMode(Drawable drawable, PorterDuff.Mode tintMode) {
132            DrawableCompatL.setTintMode(drawable, tintMode);
133        }
134    }
135
136    /**
137     * Select the correct implementation to use for the current platform.
138     */
139    static final DrawableImpl IMPL;
140    static {
141        final int version = android.os.Build.VERSION.SDK_INT;
142        if (version >= 21) {
143            IMPL = new LDrawableImpl();
144        } else if (version >= 19) {
145            IMPL = new KitKatDrawableImpl();
146        } else if (version >= 11) {
147            IMPL = new HoneycombDrawableImpl();
148        } else {
149            IMPL = new BaseDrawableImpl();
150        }
151    }
152
153    /**
154     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}.
155     * <p>
156     * If running on a pre-{@link android.os.Build.VERSION_CODES#HONEYCOMB}
157     * device this method does nothing.
158     *
159     * @param drawable The Drawable against which to invoke the method.
160     */
161    public static void jumpToCurrentState(Drawable drawable) {
162        IMPL.jumpToCurrentState(drawable);
163    }
164
165    /**
166     * Set whether this Drawable is automatically mirrored when its layout
167     * direction is RTL (right-to left). See
168     * {@link android.util.LayoutDirection}.
169     * <p>
170     * If running on a pre-{@link android.os.Build.VERSION_CODES#KITKAT} device
171     * this method does nothing.
172     *
173     * @param drawable The Drawable against which to invoke the method.
174     * @param mirrored Set to true if the Drawable should be mirrored, false if
175     *            not.
176     */
177    public static void setAutoMirrored(Drawable drawable, boolean mirrored) {
178        IMPL.setAutoMirrored(drawable, mirrored);
179    }
180
181    /**
182     * Tells if this Drawable will be automatically mirrored when its layout
183     * direction is RTL right-to-left. See {@link android.util.LayoutDirection}.
184     * <p>
185     * If running on a pre-{@link android.os.Build.VERSION_CODES#KITKAT} device
186     * this method returns false.
187     *
188     * @param drawable The Drawable against which to invoke the method.
189     * @return boolean Returns true if this Drawable will be automatically
190     *         mirrored.
191     */
192    public static boolean isAutoMirrored(Drawable drawable) {
193        return IMPL.isAutoMirrored(drawable);
194    }
195
196    /**
197     * Specifies the hotspot's location within the drawable.
198     *
199     * @param drawable The Drawable against which to invoke the method.
200     * @param x The X coordinate of the center of the hotspot
201     * @param y The Y coordinate of the center of the hotspot
202     */
203    public static void setHotspot(Drawable drawable, float x, float y) {
204        IMPL.setHotspot(drawable, x, y);
205    }
206
207    /**
208     * Sets the bounds to which the hotspot is constrained, if they should be
209     * different from the drawable bounds.
210     *
211     * @param drawable The Drawable against which to invoke the method.
212     */
213    public static void setHotspotBounds(Drawable drawable, int left, int top,
214            int right, int bottom) {
215        IMPL.setHotspotBounds(drawable, left, top, right, bottom);
216    }
217
218    /**
219     * Specifies a tint for this drawable.
220     * <p>
221     * Setting a color filter via {@link #setColorFilter(ColorFilter)} overrides
222     * tint.
223     *
224     * @param drawable The Drawable against which to invoke the method.
225     * @param tint Color to use for tinting this drawable
226     * @see #setTintMode(PorterDuff.Mode)
227     */
228    public static void setTint(Drawable drawable, int tint) {
229        IMPL.setTint(drawable, tint);
230    }
231
232    /**
233     * Specifies a tint for this drawable as a color state list.
234     * <p>
235     * Setting a color filter via {@link #setColorFilter(ColorFilter)} overrides
236     * tint.
237     *
238     * @param drawable The Drawable against which to invoke the method.
239     * @param tint Color state list to use for tinting this drawable, or null to
240     *            clear the tint
241     */
242    public static void setTintList(Drawable drawable, ColorStateList tint) {
243        IMPL.setTintList(drawable, tint);
244    }
245
246    /**
247     * Specifies a tint blending mode for this drawable.
248     * <p>
249     * Setting a color filter via {@link #setColorFilter(ColorFilter)} overrides
250     * tint.
251     *
252     * @param drawable The Drawable against which to invoke the method.
253     * @param tintMode Color state list to use for tinting this drawable, or null to
254     *            clear the tint
255     * @param tintMode A Porter-Duff blending mode
256     */
257    public static void setTintMode(Drawable drawable, PorterDuff.Mode tintMode) {
258        IMPL.setTintMode(drawable, tintMode);
259    }
260}
261