• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 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 android.graphics.drawable;
18 
19 import com.android.internal.R;
20 
21 import org.xmlpull.v1.XmlPullParser;
22 import org.xmlpull.v1.XmlPullParserException;
23 
24 import android.annotation.AttrRes;
25 import android.annotation.ColorInt;
26 import android.annotation.IntRange;
27 import android.annotation.NonNull;
28 import android.annotation.Nullable;
29 import android.annotation.TestApi;
30 import android.content.pm.ActivityInfo.Config;
31 import android.content.res.ColorStateList;
32 import android.content.res.Resources;
33 import android.content.res.Resources.Theme;
34 import android.content.res.TypedArray;
35 import android.graphics.Bitmap;
36 import android.graphics.BitmapFactory;
37 import android.graphics.Canvas;
38 import android.graphics.Color;
39 import android.graphics.ColorFilter;
40 import android.graphics.Insets;
41 import android.graphics.NinePatch;
42 import android.graphics.Outline;
43 import android.graphics.PixelFormat;
44 import android.graphics.PorterDuff;
45 import android.graphics.PorterDuff.Mode;
46 import android.graphics.PorterDuffColorFilter;
47 import android.graphics.Rect;
48 import android.graphics.Region;
49 import android.graphics.Xfermode;
50 import android.os.Trace;
51 import android.util.AttributeSet;
52 import android.util.DisplayMetrics;
53 import android.util.StateSet;
54 import android.util.TypedValue;
55 import android.util.Xml;
56 import android.view.View;
57 
58 import java.io.IOException;
59 import java.io.InputStream;
60 import java.lang.ref.WeakReference;
61 import java.util.Arrays;
62 
63 /**
64  * A Drawable is a general abstraction for "something that can be drawn."  Most
65  * often you will deal with Drawable as the type of resource retrieved for
66  * drawing things to the screen; the Drawable class provides a generic API for
67  * dealing with an underlying visual resource that may take a variety of forms.
68  * Unlike a {@link android.view.View}, a Drawable does not have any facility to
69  * receive events or otherwise interact with the user.
70  *
71  * <p>In addition to simple drawing, Drawable provides a number of generic
72  * mechanisms for its client to interact with what is being drawn:
73  *
74  * <ul>
75  *     <li> The {@link #setBounds} method <var>must</var> be called to tell the
76  *     Drawable where it is drawn and how large it should be.  All Drawables
77  *     should respect the requested size, often simply by scaling their
78  *     imagery.  A client can find the preferred size for some Drawables with
79  *     the {@link #getIntrinsicHeight} and {@link #getIntrinsicWidth} methods.
80  *
81  *     <li> The {@link #getPadding} method can return from some Drawables
82  *     information about how to frame content that is placed inside of them.
83  *     For example, a Drawable that is intended to be the frame for a button
84  *     widget would need to return padding that correctly places the label
85  *     inside of itself.
86  *
87  *     <li> The {@link #setState} method allows the client to tell the Drawable
88  *     in which state it is to be drawn, such as "focused", "selected", etc.
89  *     Some drawables may modify their imagery based on the selected state.
90  *
91  *     <li> The {@link #setLevel} method allows the client to supply a single
92  *     continuous controller that can modify the Drawable is displayed, such as
93  *     a battery level or progress level.  Some drawables may modify their
94  *     imagery based on the current level.
95  *
96  *     <li> A Drawable can perform animations by calling back to its client
97  *     through the {@link Callback} interface.  All clients should support this
98  *     interface (via {@link #setCallback}) so that animations will work.  A
99  *     simple way to do this is through the system facilities such as
100  *     {@link android.view.View#setBackground(Drawable)} and
101  *     {@link android.widget.ImageView}.
102  * </ul>
103  *
104  * Though usually not visible to the application, Drawables may take a variety
105  * of forms:
106  *
107  * <ul>
108  *     <li> <b>Bitmap</b>: the simplest Drawable, a PNG or JPEG image.
109  *     <li> <b>Nine Patch</b>: an extension to the PNG format allows it to
110  *     specify information about how to stretch it and place things inside of
111  *     it.
112  *     <li><b>Vector</b>: a drawable defined in an XML file as a set of points,
113  *     lines, and curves along with its associated color information. This type
114  *     of drawable can be scaled without loss of display quality.
115  *     <li> <b>Shape</b>: contains simple drawing commands instead of a raw
116  *     bitmap, allowing it to resize better in some cases.
117  *     <li> <b>Layers</b>: a compound drawable, which draws multiple underlying
118  *     drawables on top of each other.
119  *     <li> <b>States</b>: a compound drawable that selects one of a set of
120  *     drawables based on its state.
121  *     <li> <b>Levels</b>: a compound drawable that selects one of a set of
122  *     drawables based on its level.
123  *     <li> <b>Scale</b>: a compound drawable with a single child drawable,
124  *     whose overall size is modified based on the current level.
125  * </ul>
126  *
127  * <a name="Custom"></a>
128  * <h3>Custom drawables</h3>
129  *
130  * <p>
131  * All versions of Android allow the Drawable class to be extended and used at
132  * run time in place of framework-provided drawable classes. Starting in
133  * {@link android.os.Build.VERSION_CODES#N API 24}, custom drawables classes
134  * may also be used in XML.
135  * <p>
136  * <strong>Note:</strong> Custom drawable classes are only accessible from
137  * within your application package. Other applications will not be able to load
138  * them.
139  * <p>
140  * At a minimum, custom drawable classes must implement the abstract methods on
141  * Drawable and should override the {@link Drawable#draw(Canvas)} method to
142  * draw content.
143  * <p>
144  * Custom drawables classes may be used in XML in multiple ways:
145  * <ul>
146  *     <li>
147  *         Using the fully-qualified class name as the XML element name. For
148  *         this method, the custom drawable class must be a public top-level
149  *         class.
150  * <pre>
151  * &lt;com.myapp.MyCustomDrawable xmlns:android="http://schemas.android.com/apk/res/android"
152  *     android:color="#ffff0000" /&gt;
153  * </pre>
154  *     </li>
155  *     <li>
156  *         Using <em>drawable</em> as the XML element name and specifying the
157  *         fully-qualified class name from the <em>class</em> attribute. This
158  *         method may be used for both public top-level classes and public
159  *         static inner classes.
160  * <pre>
161  * &lt;drawable xmlns:android="http://schemas.android.com/apk/res/android"
162  *     class="com.myapp.MyTopLevelClass$InnerCustomDrawable"
163  *     android:color="#ffff0000" /&gt;
164  * </pre>
165  *     </li>
166  * </ul>
167  *
168  * <div class="special reference">
169  * <h3>Developer Guides</h3>
170  * <p>For more information about how to use drawables, read the
171  * <a href="{@docRoot}guide/topics/graphics/2d-graphics.html">Canvas and Drawables</a> developer
172  * guide. For information and examples of creating drawable resources (XML or bitmap files that
173  * can be loaded in code), read the
174  * <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>
175  * document.</p></div>
176  */
177 public abstract class Drawable {
178     private static final Rect ZERO_BOUNDS_RECT = new Rect();
179 
180     static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN;
181 
182     private int[] mStateSet = StateSet.WILD_CARD;
183     private int mLevel = 0;
184     private @Config int mChangingConfigurations = 0;
185     private Rect mBounds = ZERO_BOUNDS_RECT;  // lazily becomes a new Rect()
186     private WeakReference<Callback> mCallback = null;
187     private boolean mVisible = true;
188 
189     private int mLayoutDirection;
190 
191     /**
192      * The source density to use when looking up resources using
193      * {@link Resources#getDrawableForDensity(int, int, Theme)}. A value of 0 means there is no
194      * override and the system density will be used.
195      *
196      * NOTE(adamlesinski): This is transient state used to get around the public API that does not
197      * account for source density overrides. Custom drawables implemented by developers do not need
198      * to be aware of the source density override, as it is only used by Launcher to load higher
199      * resolution icons from external Resources packages, which do not execute custom code.
200      * This is all to support the {@link Resources#getDrawableForDensity(int, int, Theme)} API.
201      *
202      * @hide
203      */
204     protected int mSrcDensityOverride = 0;
205 
206     /**
207      * Draw in its bounds (set via setBounds) respecting optional effects such
208      * as alpha (set via setAlpha) and color filter (set via setColorFilter).
209      *
210      * @param canvas The canvas to draw into
211      */
draw(@onNull Canvas canvas)212     public abstract void draw(@NonNull Canvas canvas);
213 
214     /**
215      * Specify a bounding rectangle for the Drawable. This is where the drawable
216      * will draw when its draw() method is called.
217      */
setBounds(int left, int top, int right, int bottom)218     public void setBounds(int left, int top, int right, int bottom) {
219         Rect oldBounds = mBounds;
220 
221         if (oldBounds == ZERO_BOUNDS_RECT) {
222             oldBounds = mBounds = new Rect();
223         }
224 
225         if (oldBounds.left != left || oldBounds.top != top ||
226                 oldBounds.right != right || oldBounds.bottom != bottom) {
227             if (!oldBounds.isEmpty()) {
228                 // first invalidate the previous bounds
229                 invalidateSelf();
230             }
231             mBounds.set(left, top, right, bottom);
232             onBoundsChange(mBounds);
233         }
234     }
235 
236     /**
237      * Specify a bounding rectangle for the Drawable. This is where the drawable
238      * will draw when its draw() method is called.
239      */
setBounds(@onNull Rect bounds)240     public void setBounds(@NonNull Rect bounds) {
241         setBounds(bounds.left, bounds.top, bounds.right, bounds.bottom);
242     }
243 
244     /**
245      * Return a copy of the drawable's bounds in the specified Rect (allocated
246      * by the caller). The bounds specify where this will draw when its draw()
247      * method is called.
248      *
249      * @param bounds Rect to receive the drawable's bounds (allocated by the
250      *               caller).
251      */
copyBounds(@onNull Rect bounds)252     public final void copyBounds(@NonNull Rect bounds) {
253         bounds.set(mBounds);
254     }
255 
256     /**
257      * Return a copy of the drawable's bounds in a new Rect. This returns the
258      * same values as getBounds(), but the returned object is guaranteed to not
259      * be changed later by the drawable (i.e. it retains no reference to this
260      * rect). If the caller already has a Rect allocated, call copyBounds(rect).
261      *
262      * @return A copy of the drawable's bounds
263      */
264     @NonNull
copyBounds()265     public final Rect copyBounds() {
266         return new Rect(mBounds);
267     }
268 
269     /**
270      * Return the drawable's bounds Rect. Note: for efficiency, the returned
271      * object may be the same object stored in the drawable (though this is not
272      * guaranteed), so if a persistent copy of the bounds is needed, call
273      * copyBounds(rect) instead.
274      * You should also not change the object returned by this method as it may
275      * be the same object stored in the drawable.
276      *
277      * @return The bounds of the drawable (which may change later, so caller
278      *         beware). DO NOT ALTER the returned object as it may change the
279      *         stored bounds of this drawable.
280      *
281      * @see #copyBounds()
282      * @see #copyBounds(android.graphics.Rect)
283      */
284     @NonNull
getBounds()285     public final Rect getBounds() {
286         if (mBounds == ZERO_BOUNDS_RECT) {
287             mBounds = new Rect();
288         }
289 
290         return mBounds;
291     }
292 
293     /**
294      * Return the drawable's dirty bounds Rect. Note: for efficiency, the
295      * returned object may be the same object stored in the drawable (though
296      * this is not guaranteed).
297      * <p>
298      * By default, this returns the full drawable bounds. Custom drawables may
299      * override this method to perform more precise invalidation.
300      *
301      * @return The dirty bounds of this drawable
302      */
303     @NonNull
getDirtyBounds()304     public Rect getDirtyBounds() {
305         return getBounds();
306     }
307 
308     /**
309      * Set a mask of the configuration parameters for which this drawable
310      * may change, requiring that it be re-created.
311      *
312      * @param configs A mask of the changing configuration parameters, as
313      * defined by {@link android.content.pm.ActivityInfo}.
314      *
315      * @see android.content.pm.ActivityInfo
316      */
setChangingConfigurations(@onfig int configs)317     public void setChangingConfigurations(@Config int configs) {
318         mChangingConfigurations = configs;
319     }
320 
321     /**
322      * Return a mask of the configuration parameters for which this drawable
323      * may change, requiring that it be re-created.  The default implementation
324      * returns whatever was provided through
325      * {@link #setChangingConfigurations(int)} or 0 by default.  Subclasses
326      * may extend this to or in the changing configurations of any other
327      * drawables they hold.
328      *
329      * @return Returns a mask of the changing configuration parameters, as
330      * defined by {@link android.content.pm.ActivityInfo}.
331      *
332      * @see android.content.pm.ActivityInfo
333      */
getChangingConfigurations()334     public @Config int getChangingConfigurations() {
335         return mChangingConfigurations;
336     }
337 
338     /**
339      * Set to true to have the drawable dither its colors when drawn to a
340      * device with fewer than 8-bits per color component.
341      *
342      * @see android.graphics.Paint#setDither(boolean);
343      * @deprecated This property is ignored.
344      */
345     @Deprecated
setDither(boolean dither)346     public void setDither(boolean dither) {}
347 
348     /**
349      * Set to true to have the drawable filter its bitmaps with bilinear
350      * sampling when they are scaled or rotated.
351      *
352      * <p>This can improve appearance when bitmaps are rotated. If the drawable
353      * does not use bitmaps, this call is ignored.</p>
354      *
355      * @see #isFilterBitmap()
356      * @see android.graphics.Paint#setFilterBitmap(boolean);
357      */
setFilterBitmap(boolean filter)358     public void setFilterBitmap(boolean filter) {}
359 
360     /**
361      * @return whether this drawable filters its bitmaps
362      * @see #setFilterBitmap(boolean)
363      */
isFilterBitmap()364     public boolean isFilterBitmap() {
365         return false;
366     }
367 
368     /**
369      * Implement this interface if you want to create an animated drawable that
370      * extends {@link android.graphics.drawable.Drawable Drawable}.
371      * Upon retrieving a drawable, use
372      * {@link Drawable#setCallback(android.graphics.drawable.Drawable.Callback)}
373      * to supply your implementation of the interface to the drawable; it uses
374      * this interface to schedule and execute animation changes.
375      */
376     public interface Callback {
377         /**
378          * Called when the drawable needs to be redrawn.  A view at this point
379          * should invalidate itself (or at least the part of itself where the
380          * drawable appears).
381          *
382          * @param who The drawable that is requesting the update.
383          */
invalidateDrawable(@onNull Drawable who)384         void invalidateDrawable(@NonNull Drawable who);
385 
386         /**
387          * A Drawable can call this to schedule the next frame of its
388          * animation.  An implementation can generally simply call
389          * {@link android.os.Handler#postAtTime(Runnable, Object, long)} with
390          * the parameters <var>(what, who, when)</var> to perform the
391          * scheduling.
392          *
393          * @param who The drawable being scheduled.
394          * @param what The action to execute.
395          * @param when The time (in milliseconds) to run.  The timebase is
396          *             {@link android.os.SystemClock#uptimeMillis}
397          */
scheduleDrawable(@onNull Drawable who, @NonNull Runnable what, long when)398         void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when);
399 
400         /**
401          * A Drawable can call this to unschedule an action previously
402          * scheduled with {@link #scheduleDrawable}.  An implementation can
403          * generally simply call
404          * {@link android.os.Handler#removeCallbacks(Runnable, Object)} with
405          * the parameters <var>(what, who)</var> to unschedule the drawable.
406          *
407          * @param who The drawable being unscheduled.
408          * @param what The action being unscheduled.
409          */
unscheduleDrawable(@onNull Drawable who, @NonNull Runnable what)410         void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what);
411     }
412 
413     /**
414      * Bind a {@link Callback} object to this Drawable.  Required for clients
415      * that want to support animated drawables.
416      *
417      * @param cb The client's Callback implementation.
418      *
419      * @see #getCallback()
420      */
setCallback(@ullable Callback cb)421     public final void setCallback(@Nullable Callback cb) {
422         mCallback = cb != null ? new WeakReference<>(cb) : null;
423     }
424 
425     /**
426      * Return the current {@link Callback} implementation attached to this
427      * Drawable.
428      *
429      * @return A {@link Callback} instance or null if no callback was set.
430      *
431      * @see #setCallback(android.graphics.drawable.Drawable.Callback)
432      */
433     @Nullable
getCallback()434     public Callback getCallback() {
435         return mCallback != null ? mCallback.get() : null;
436     }
437 
438     /**
439      * Use the current {@link Callback} implementation to have this Drawable
440      * redrawn.  Does nothing if there is no Callback attached to the
441      * Drawable.
442      *
443      * @see Callback#invalidateDrawable
444      * @see #getCallback()
445      * @see #setCallback(android.graphics.drawable.Drawable.Callback)
446      */
invalidateSelf()447     public void invalidateSelf() {
448         final Callback callback = getCallback();
449         if (callback != null) {
450             callback.invalidateDrawable(this);
451         }
452     }
453 
454     /**
455      * Use the current {@link Callback} implementation to have this Drawable
456      * scheduled.  Does nothing if there is no Callback attached to the
457      * Drawable.
458      *
459      * @param what The action being scheduled.
460      * @param when The time (in milliseconds) to run.
461      *
462      * @see Callback#scheduleDrawable
463      */
scheduleSelf(@onNull Runnable what, long when)464     public void scheduleSelf(@NonNull Runnable what, long when) {
465         final Callback callback = getCallback();
466         if (callback != null) {
467             callback.scheduleDrawable(this, what, when);
468         }
469     }
470 
471     /**
472      * Use the current {@link Callback} implementation to have this Drawable
473      * unscheduled.  Does nothing if there is no Callback attached to the
474      * Drawable.
475      *
476      * @param what The runnable that you no longer want called.
477      *
478      * @see Callback#unscheduleDrawable
479      */
unscheduleSelf(@onNull Runnable what)480     public void unscheduleSelf(@NonNull Runnable what) {
481         final Callback callback = getCallback();
482         if (callback != null) {
483             callback.unscheduleDrawable(this, what);
484         }
485     }
486 
487     /**
488      * Returns the resolved layout direction for this Drawable.
489      *
490      * @return One of {@link android.view.View#LAYOUT_DIRECTION_LTR},
491      *         {@link android.view.View#LAYOUT_DIRECTION_RTL}
492      * @see #setLayoutDirection(int)
493      */
getLayoutDirection()494     public @View.ResolvedLayoutDir int getLayoutDirection() {
495         return mLayoutDirection;
496     }
497 
498     /**
499      * Set the layout direction for this drawable. Should be a resolved
500      * layout direction, as the Drawable has no capacity to do the resolution on
501      * its own.
502      *
503      * @param layoutDirection the resolved layout direction for the drawable,
504      *                        either {@link android.view.View#LAYOUT_DIRECTION_LTR}
505      *                        or {@link android.view.View#LAYOUT_DIRECTION_RTL}
506      * @return {@code true} if the layout direction change has caused the
507      *         appearance of the drawable to change such that it needs to be
508      *         re-drawn, {@code false} otherwise
509      * @see #getLayoutDirection()
510      */
setLayoutDirection(@iew.ResolvedLayoutDir int layoutDirection)511     public final boolean setLayoutDirection(@View.ResolvedLayoutDir int layoutDirection) {
512         if (mLayoutDirection != layoutDirection) {
513             mLayoutDirection = layoutDirection;
514             return onLayoutDirectionChanged(layoutDirection);
515         }
516         return false;
517     }
518 
519     /**
520      * Called when the drawable's resolved layout direction changes.
521      *
522      * @param layoutDirection the new resolved layout direction
523      * @return {@code true} if the layout direction change has caused the
524      *         appearance of the drawable to change such that it needs to be
525      *         re-drawn, {@code false} otherwise
526      * @see #setLayoutDirection(int)
527      */
onLayoutDirectionChanged(@iew.ResolvedLayoutDir int layoutDirection)528     public boolean onLayoutDirectionChanged(@View.ResolvedLayoutDir int layoutDirection) {
529         return false;
530     }
531 
532     /**
533      * Specify an alpha value for the drawable. 0 means fully transparent, and
534      * 255 means fully opaque.
535      */
setAlpha(@ntRangefrom=0,to=255) int alpha)536     public abstract void setAlpha(@IntRange(from=0,to=255) int alpha);
537 
538     /**
539      * Gets the current alpha value for the drawable. 0 means fully transparent,
540      * 255 means fully opaque. This method is implemented by
541      * Drawable subclasses and the value returned is specific to how that class treats alpha.
542      * The default return value is 255 if the class does not override this method to return a value
543      * specific to its use of alpha.
544      */
545     @IntRange(from=0,to=255)
getAlpha()546     public int getAlpha() {
547         return 0xFF;
548     }
549 
550     /**
551      * @hide
552      *
553      * Internal-only method for setting xfermode on certain supported drawables.
554      *
555      * Should not be made public since the layers and drawing area with which
556      * Drawables draw is private implementation detail, and not something apps
557      * should rely upon.
558      */
setXfermode(@ullable Xfermode mode)559     public void setXfermode(@Nullable Xfermode mode) {
560         // Base implementation drops it on the floor for compatibility. Whee!
561     }
562 
563     /**
564      * Specify an optional color filter for the drawable.
565      * <p>
566      * If a Drawable has a ColorFilter, each output pixel of the Drawable's
567      * drawing contents will be modified by the color filter before it is
568      * blended onto the render target of a Canvas.
569      * </p>
570      * <p>
571      * Pass {@code null} to remove any existing color filter.
572      * </p>
573      * <p class="note"><strong>Note:</strong> Setting a non-{@code null} color
574      * filter disables {@link #setTintList(ColorStateList) tint}.
575      * </p>
576      *
577      * @param colorFilter The color filter to apply, or {@code null} to remove the
578      *            existing color filter
579      */
setColorFilter(@ullable ColorFilter colorFilter)580     public abstract void setColorFilter(@Nullable ColorFilter colorFilter);
581 
582     /**
583      * Specify a color and Porter-Duff mode to be the color filter for this
584      * drawable.
585      * <p>
586      * Convenience for {@link #setColorFilter(ColorFilter)} which constructs a
587      * {@link PorterDuffColorFilter}.
588      * </p>
589      * <p class="note"><strong>Note:</strong> Setting a color filter disables
590      * {@link #setTintList(ColorStateList) tint}.
591      * </p>
592      */
setColorFilter(@olorInt int color, @NonNull PorterDuff.Mode mode)593     public void setColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
594         if (getColorFilter() instanceof PorterDuffColorFilter) {
595             PorterDuffColorFilter existing = (PorterDuffColorFilter) getColorFilter();
596             if (existing.getColor() == color && existing.getMode() == mode) {
597                 return;
598             }
599         }
600         setColorFilter(new PorterDuffColorFilter(color, mode));
601     }
602 
603     /**
604      * Specifies tint color for this drawable.
605      * <p>
606      * A Drawable's drawing content will be blended together with its tint
607      * before it is drawn to the screen. This functions similarly to
608      * {@link #setColorFilter(int, PorterDuff.Mode)}.
609      * </p>
610      * <p>
611      * To clear the tint, pass {@code null} to
612      * {@link #setTintList(ColorStateList)}.
613      * </p>
614      * <p class="note"><strong>Note:</strong> Setting a color filter via
615      * {@link #setColorFilter(ColorFilter)} or
616      * {@link #setColorFilter(int, PorterDuff.Mode)} overrides tint.
617      * </p>
618      *
619      * @param tintColor Color to use for tinting this drawable
620      * @see #setTintList(ColorStateList)
621      * @see #setTintMode(PorterDuff.Mode)
622      */
setTint(@olorInt int tintColor)623     public void setTint(@ColorInt int tintColor) {
624         setTintList(ColorStateList.valueOf(tintColor));
625     }
626 
627     /**
628      * Specifies tint color for this drawable as a color state list.
629      * <p>
630      * A Drawable's drawing content will be blended together with its tint
631      * before it is drawn to the screen. This functions similarly to
632      * {@link #setColorFilter(int, PorterDuff.Mode)}.
633      * </p>
634      * <p class="note"><strong>Note:</strong> Setting a color filter via
635      * {@link #setColorFilter(ColorFilter)} or
636      * {@link #setColorFilter(int, PorterDuff.Mode)} overrides tint.
637      * </p>
638      *
639      * @param tint Color state list to use for tinting this drawable, or
640      *            {@code null} to clear the tint
641      * @see #setTint(int)
642      * @see #setTintMode(PorterDuff.Mode)
643      */
setTintList(@ullable ColorStateList tint)644     public void setTintList(@Nullable ColorStateList tint) {}
645 
646     /**
647      * Specifies a tint blending mode for this drawable.
648      * <p>
649      * Defines how this drawable's tint color should be blended into the drawable
650      * before it is drawn to screen. Default tint mode is {@link PorterDuff.Mode#SRC_IN}.
651      * </p>
652      * <p class="note"><strong>Note:</strong> Setting a color filter via
653      * {@link #setColorFilter(ColorFilter)} or
654      * {@link #setColorFilter(int, PorterDuff.Mode)} overrides tint.
655      * </p>
656      *
657      * @param tintMode A Porter-Duff blending mode
658      * @see #setTint(int)
659      * @see #setTintList(ColorStateList)
660      */
setTintMode(@onNull PorterDuff.Mode tintMode)661     public void setTintMode(@NonNull PorterDuff.Mode tintMode) {}
662 
663     /**
664      * Returns the current color filter, or {@code null} if none set.
665      *
666      * @return the current color filter, or {@code null} if none set
667      */
getColorFilter()668     public @Nullable ColorFilter getColorFilter() {
669         return null;
670     }
671 
672     /**
673      * Removes the color filter for this drawable.
674      */
clearColorFilter()675     public void clearColorFilter() {
676         setColorFilter(null);
677     }
678 
679     /**
680      * Specifies the hotspot's location within the drawable.
681      *
682      * @param x The X coordinate of the center of the hotspot
683      * @param y The Y coordinate of the center of the hotspot
684      */
setHotspot(float x, float y)685     public void setHotspot(float x, float y) {}
686 
687     /**
688      * Sets the bounds to which the hotspot is constrained, if they should be
689      * different from the drawable bounds.
690      *
691      * @param left position in pixels of the left bound
692      * @param top position in pixels of the top bound
693      * @param right position in pixels of the right bound
694      * @param bottom position in pixels of the bottom bound
695      * @see #getHotspotBounds(android.graphics.Rect)
696      */
setHotspotBounds(int left, int top, int right, int bottom)697     public void setHotspotBounds(int left, int top, int right, int bottom) {}
698 
699     /**
700      * Populates {@code outRect} with the hotspot bounds.
701      *
702      * @param outRect the rect to populate with the hotspot bounds
703      * @see #setHotspotBounds(int, int, int, int)
704      */
getHotspotBounds(@onNull Rect outRect)705     public void getHotspotBounds(@NonNull Rect outRect) {
706         outRect.set(getBounds());
707     }
708 
709     /**
710      * Whether this drawable requests projection.
711      *
712      * @hide magic!
713      */
isProjected()714     public boolean isProjected() {
715         return false;
716     }
717 
718     /**
719      * Indicates whether this drawable will change its appearance based on
720      * state. Clients can use this to determine whether it is necessary to
721      * calculate their state and call setState.
722      *
723      * @return True if this drawable changes its appearance based on state,
724      *         false otherwise.
725      * @see #setState(int[])
726      */
isStateful()727     public boolean isStateful() {
728         return false;
729     }
730 
731     /**
732      * Indicates whether this drawable has at least one state spec explicitly
733      * specifying {@link android.R.attr#state_focused}.
734      *
735      * <p>Note: A View uses a {@link Drawable} instance as its background and it
736      * changes its appearance based on a state. On keyboard devices, it should
737      * specify its {@link android.R.attr#state_focused} to make sure the user
738      * knows which view is holding the focus.</p>
739      *
740      * @return {@code true} if {@link android.R.attr#state_focused} is specified
741      * for this drawable.
742      *
743      * @hide
744      */
745     @TestApi
hasFocusStateSpecified()746     public boolean hasFocusStateSpecified() {
747         return false;
748     }
749 
750     /**
751      * Specify a set of states for the drawable. These are use-case specific,
752      * so see the relevant documentation. As an example, the background for
753      * widgets like Button understand the following states:
754      * [{@link android.R.attr#state_focused},
755      *  {@link android.R.attr#state_pressed}].
756      *
757      * <p>If the new state you are supplying causes the appearance of the
758      * Drawable to change, then it is responsible for calling
759      * {@link #invalidateSelf} in order to have itself redrawn, <em>and</em>
760      * true will be returned from this function.
761      *
762      * <p>Note: The Drawable holds a reference on to <var>stateSet</var>
763      * until a new state array is given to it, so you must not modify this
764      * array during that time.</p>
765      *
766      * @param stateSet The new set of states to be displayed.
767      *
768      * @return Returns true if this change in state has caused the appearance
769      * of the Drawable to change (hence requiring an invalidate), otherwise
770      * returns false.
771      */
setState(@onNull final int[] stateSet)772     public boolean setState(@NonNull final int[] stateSet) {
773         if (!Arrays.equals(mStateSet, stateSet)) {
774             mStateSet = stateSet;
775             return onStateChange(stateSet);
776         }
777         return false;
778     }
779 
780     /**
781      * Describes the current state, as a union of primitve states, such as
782      * {@link android.R.attr#state_focused},
783      * {@link android.R.attr#state_selected}, etc.
784      * Some drawables may modify their imagery based on the selected state.
785      * @return An array of resource Ids describing the current state.
786      */
getState()787     public @NonNull int[] getState() {
788         return mStateSet;
789     }
790 
791     /**
792      * If this Drawable does transition animations between states, ask that
793      * it immediately jump to the current state and skip any active animations.
794      */
jumpToCurrentState()795     public void jumpToCurrentState() {
796     }
797 
798     /**
799      * @return The current drawable that will be used by this drawable. For simple drawables, this
800      *         is just the drawable itself. For drawables that change state like
801      *         {@link StateListDrawable} and {@link LevelListDrawable} this will be the child drawable
802      *         currently in use.
803      */
getCurrent()804     public @NonNull Drawable getCurrent() {
805         return this;
806     }
807 
808     /**
809      * Specify the level for the drawable.  This allows a drawable to vary its
810      * imagery based on a continuous controller, for example to show progress
811      * or volume level.
812      *
813      * <p>If the new level you are supplying causes the appearance of the
814      * Drawable to change, then it is responsible for calling
815      * {@link #invalidateSelf} in order to have itself redrawn, <em>and</em>
816      * true will be returned from this function.
817      *
818      * @param level The new level, from 0 (minimum) to 10000 (maximum).
819      *
820      * @return Returns true if this change in level has caused the appearance
821      * of the Drawable to change (hence requiring an invalidate), otherwise
822      * returns false.
823      */
setLevel(@ntRangefrom=0,to=10000) int level)824     public final boolean setLevel(@IntRange(from=0,to=10000) int level) {
825         if (mLevel != level) {
826             mLevel = level;
827             return onLevelChange(level);
828         }
829         return false;
830     }
831 
832     /**
833      * Retrieve the current level.
834      *
835      * @return int Current level, from 0 (minimum) to 10000 (maximum).
836      */
getLevel()837     public final @IntRange(from=0,to=10000) int getLevel() {
838         return mLevel;
839     }
840 
841     /**
842      * Set whether this Drawable is visible.  This generally does not impact
843      * the Drawable's behavior, but is a hint that can be used by some
844      * Drawables, for example, to decide whether run animations.
845      *
846      * @param visible Set to true if visible, false if not.
847      * @param restart You can supply true here to force the drawable to behave
848      *                as if it has just become visible, even if it had last
849      *                been set visible.  Used for example to force animations
850      *                to restart.
851      *
852      * @return boolean Returns true if the new visibility is different than
853      *         its previous state.
854      */
setVisible(boolean visible, boolean restart)855     public boolean setVisible(boolean visible, boolean restart) {
856         boolean changed = mVisible != visible;
857         if (changed) {
858             mVisible = visible;
859             invalidateSelf();
860         }
861         return changed;
862     }
863 
isVisible()864     public final boolean isVisible() {
865         return mVisible;
866     }
867 
868     /**
869      * Set whether this Drawable is automatically mirrored when its layout direction is RTL
870      * (right-to left). See {@link android.util.LayoutDirection}.
871      *
872      * @param mirrored Set to true if the Drawable should be mirrored, false if not.
873      */
setAutoMirrored(boolean mirrored)874     public void setAutoMirrored(boolean mirrored) {
875     }
876 
877     /**
878      * Tells if this Drawable will be automatically mirrored  when its layout direction is RTL
879      * right-to-left. See {@link android.util.LayoutDirection}.
880      *
881      * @return boolean Returns true if this Drawable will be automatically mirrored.
882      */
isAutoMirrored()883     public boolean isAutoMirrored() {
884         return false;
885     }
886 
887     /**
888      * Applies the specified theme to this Drawable and its children.
889      *
890      * @param t the theme to apply
891      */
applyTheme(@onNull @uppressWarnings"unused") Theme t)892     public void applyTheme(@NonNull @SuppressWarnings("unused") Theme t) {
893     }
894 
canApplyTheme()895     public boolean canApplyTheme() {
896         return false;
897     }
898 
899     /**
900      * Return the opacity/transparency of this Drawable.  The returned value is
901      * one of the abstract format constants in
902      * {@link android.graphics.PixelFormat}:
903      * {@link android.graphics.PixelFormat#UNKNOWN},
904      * {@link android.graphics.PixelFormat#TRANSLUCENT},
905      * {@link android.graphics.PixelFormat#TRANSPARENT}, or
906      * {@link android.graphics.PixelFormat#OPAQUE}.
907      *
908      * <p>An OPAQUE drawable is one that draws all all content within its bounds, completely
909      * covering anything behind the drawable. A TRANSPARENT drawable is one that draws nothing
910      * within its bounds, allowing everything behind it to show through. A TRANSLUCENT drawable
911      * is a drawable in any other state, where the drawable will draw some, but not all,
912      * of the content within its bounds and at least some content behind the drawable will
913      * be visible. If the visibility of the drawable's contents cannot be determined, the
914      * safest/best return value is TRANSLUCENT.
915      *
916      * <p>Generally a Drawable should be as conservative as possible with the
917      * value it returns.  For example, if it contains multiple child drawables
918      * and only shows one of them at a time, if only one of the children is
919      * TRANSLUCENT and the others are OPAQUE then TRANSLUCENT should be
920      * returned.  You can use the method {@link #resolveOpacity} to perform a
921      * standard reduction of two opacities to the appropriate single output.
922      *
923      * <p>Note that the returned value does not necessarily take into account a
924      * custom alpha or color filter that has been applied by the client through
925      * the {@link #setAlpha} or {@link #setColorFilter} methods. Some subclasses,
926      * such as {@link BitmapDrawable}, {@link ColorDrawable}, and {@link GradientDrawable},
927      * do account for the value of {@link #setAlpha}, but the general behavior is dependent
928      * upon the implementation of the subclass.
929      *
930      * @return int The opacity class of the Drawable.
931      *
932      * @see android.graphics.PixelFormat
933      */
getOpacity()934     public abstract @PixelFormat.Opacity int getOpacity();
935 
936     /**
937      * Return the appropriate opacity value for two source opacities.  If
938      * either is UNKNOWN, that is returned; else, if either is TRANSLUCENT,
939      * that is returned; else, if either is TRANSPARENT, that is returned;
940      * else, OPAQUE is returned.
941      *
942      * <p>This is to help in implementing {@link #getOpacity}.
943      *
944      * @param op1 One opacity value.
945      * @param op2 Another opacity value.
946      *
947      * @return int The combined opacity value.
948      *
949      * @see #getOpacity
950      */
resolveOpacity(@ixelFormat.Opacity int op1, @PixelFormat.Opacity int op2)951     public static @PixelFormat.Opacity int resolveOpacity(@PixelFormat.Opacity int op1,
952             @PixelFormat.Opacity int op2) {
953         if (op1 == op2) {
954             return op1;
955         }
956         if (op1 == PixelFormat.UNKNOWN || op2 == PixelFormat.UNKNOWN) {
957             return PixelFormat.UNKNOWN;
958         }
959         if (op1 == PixelFormat.TRANSLUCENT || op2 == PixelFormat.TRANSLUCENT) {
960             return PixelFormat.TRANSLUCENT;
961         }
962         if (op1 == PixelFormat.TRANSPARENT || op2 == PixelFormat.TRANSPARENT) {
963             return PixelFormat.TRANSPARENT;
964         }
965         return PixelFormat.OPAQUE;
966     }
967 
968     /**
969      * Returns a Region representing the part of the Drawable that is completely
970      * transparent.  This can be used to perform drawing operations, identifying
971      * which parts of the target will not change when rendering the Drawable.
972      * The default implementation returns null, indicating no transparent
973      * region; subclasses can optionally override this to return an actual
974      * Region if they want to supply this optimization information, but it is
975      * not required that they do so.
976      *
977      * @return Returns null if the Drawables has no transparent region to
978      * report, else a Region holding the parts of the Drawable's bounds that
979      * are transparent.
980      */
getTransparentRegion()981     public @Nullable Region getTransparentRegion() {
982         return null;
983     }
984 
985     /**
986      * Override this in your subclass to change appearance if you recognize the
987      * specified state.
988      *
989      * @return Returns true if the state change has caused the appearance of
990      * the Drawable to change (that is, it needs to be drawn), else false
991      * if it looks the same and there is no need to redraw it since its
992      * last state.
993      */
onStateChange(int[] state)994     protected boolean onStateChange(int[] state) {
995         return false;
996     }
997 
998     /** Override this in your subclass to change appearance if you vary based
999      *  on level.
1000      * @return Returns true if the level change has caused the appearance of
1001      * the Drawable to change (that is, it needs to be drawn), else false
1002      * if it looks the same and there is no need to redraw it since its
1003      * last level.
1004      */
onLevelChange(int level)1005     protected boolean onLevelChange(int level) {
1006         return false;
1007     }
1008 
1009     /**
1010      * Override this in your subclass to change appearance if you vary based on
1011      * the bounds.
1012      */
onBoundsChange(Rect bounds)1013     protected void onBoundsChange(Rect bounds) {
1014         // Stub method.
1015     }
1016 
1017     /**
1018      * Returns the drawable's intrinsic width.
1019      * <p>
1020      * Intrinsic width is the width at which the drawable would like to be laid
1021      * out, including any inherent padding. If the drawable has no intrinsic
1022      * width, such as a solid color, this method returns -1.
1023      *
1024      * @return the intrinsic width, or -1 if no intrinsic width
1025      */
getIntrinsicWidth()1026     public int getIntrinsicWidth() {
1027         return -1;
1028     }
1029 
1030     /**
1031      * Returns the drawable's intrinsic height.
1032      * <p>
1033      * Intrinsic height is the height at which the drawable would like to be
1034      * laid out, including any inherent padding. If the drawable has no
1035      * intrinsic height, such as a solid color, this method returns -1.
1036      *
1037      * @return the intrinsic height, or -1 if no intrinsic height
1038      */
getIntrinsicHeight()1039     public int getIntrinsicHeight() {
1040         return -1;
1041     }
1042 
1043     /**
1044      * Returns the minimum width suggested by this Drawable. If a View uses this
1045      * Drawable as a background, it is suggested that the View use at least this
1046      * value for its width. (There will be some scenarios where this will not be
1047      * possible.) This value should INCLUDE any padding.
1048      *
1049      * @return The minimum width suggested by this Drawable. If this Drawable
1050      *         doesn't have a suggested minimum width, 0 is returned.
1051      */
getMinimumWidth()1052     public int getMinimumWidth() {
1053         final int intrinsicWidth = getIntrinsicWidth();
1054         return intrinsicWidth > 0 ? intrinsicWidth : 0;
1055     }
1056 
1057     /**
1058      * Returns the minimum height suggested by this Drawable. If a View uses this
1059      * Drawable as a background, it is suggested that the View use at least this
1060      * value for its height. (There will be some scenarios where this will not be
1061      * possible.) This value should INCLUDE any padding.
1062      *
1063      * @return The minimum height suggested by this Drawable. If this Drawable
1064      *         doesn't have a suggested minimum height, 0 is returned.
1065      */
getMinimumHeight()1066     public int getMinimumHeight() {
1067         final int intrinsicHeight = getIntrinsicHeight();
1068         return intrinsicHeight > 0 ? intrinsicHeight : 0;
1069     }
1070 
1071     /**
1072      * Return in padding the insets suggested by this Drawable for placing
1073      * content inside the drawable's bounds. Positive values move toward the
1074      * center of the Drawable (set Rect.inset).
1075      *
1076      * @return true if this drawable actually has a padding, else false. When false is returned,
1077      * the padding is always set to 0.
1078      */
getPadding(@onNull Rect padding)1079     public boolean getPadding(@NonNull Rect padding) {
1080         padding.set(0, 0, 0, 0);
1081         return false;
1082     }
1083 
1084     /**
1085      * Return in insets the layout insets suggested by this Drawable for use with alignment
1086      * operations during layout.
1087      *
1088      * @hide
1089      */
getOpticalInsets()1090     public @NonNull Insets getOpticalInsets() {
1091         return Insets.NONE;
1092     }
1093 
1094     /**
1095      * Called to get the drawable to populate the Outline that defines its drawing area.
1096      * <p>
1097      * This method is called by the default {@link android.view.ViewOutlineProvider} to define
1098      * the outline of the View.
1099      * <p>
1100      * The default behavior defines the outline to be the bounding rectangle of 0 alpha.
1101      * Subclasses that wish to convey a different shape or alpha value must override this method.
1102      *
1103      * @see android.view.View#setOutlineProvider(android.view.ViewOutlineProvider)
1104      */
getOutline(@onNull Outline outline)1105     public void getOutline(@NonNull Outline outline) {
1106         outline.setRect(getBounds());
1107         outline.setAlpha(0);
1108     }
1109 
1110     /**
1111      * Make this drawable mutable. This operation cannot be reversed. A mutable
1112      * drawable is guaranteed to not share its state with any other drawable.
1113      * This is especially useful when you need to modify properties of drawables
1114      * loaded from resources. By default, all drawables instances loaded from
1115      * the same resource share a common state; if you modify the state of one
1116      * instance, all the other instances will receive the same modification.
1117      *
1118      * Calling this method on a mutable Drawable will have no effect.
1119      *
1120      * @return This drawable.
1121      * @see ConstantState
1122      * @see #getConstantState()
1123      */
mutate()1124     public @NonNull Drawable mutate() {
1125         return this;
1126     }
1127 
1128     /**
1129      * Clears the mutated state, allowing this drawable to be cached and
1130      * mutated again.
1131      * <p>
1132      * This is hidden because only framework drawables can be cached, so
1133      * custom drawables don't need to support constant state, mutate(), or
1134      * clearMutated().
1135      *
1136      * @hide
1137      */
clearMutated()1138     public void clearMutated() {
1139         // Default implementation is no-op.
1140     }
1141 
1142     /**
1143      * Create a drawable from an inputstream
1144      */
createFromStream(InputStream is, String srcName)1145     public static Drawable createFromStream(InputStream is, String srcName) {
1146         Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, srcName != null ? srcName : "Unknown drawable");
1147         try {
1148             return createFromResourceStream(null, null, is, srcName);
1149         } finally {
1150             Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
1151         }
1152     }
1153 
1154     /**
1155      * Create a drawable from an inputstream, using the given resources and
1156      * value to determine density information.
1157      */
createFromResourceStream(Resources res, TypedValue value, InputStream is, String srcName)1158     public static Drawable createFromResourceStream(Resources res, TypedValue value,
1159             InputStream is, String srcName) {
1160         Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, srcName != null ? srcName : "Unknown drawable");
1161         try {
1162             return createFromResourceStream(res, value, is, srcName, null);
1163         } finally {
1164             Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
1165         }
1166     }
1167 
1168     /**
1169      * Create a drawable from an inputstream, using the given resources and
1170      * value to determine density information.
1171      */
createFromResourceStream(Resources res, TypedValue value, InputStream is, String srcName, BitmapFactory.Options opts)1172     public static Drawable createFromResourceStream(Resources res, TypedValue value,
1173             InputStream is, String srcName, BitmapFactory.Options opts) {
1174         if (is == null) {
1175             return null;
1176         }
1177 
1178         /*  ugh. The decodeStream contract is that we have already allocated
1179             the pad rect, but if the bitmap does not had a ninepatch chunk,
1180             then the pad will be ignored. If we could change this to lazily
1181             alloc/assign the rect, we could avoid the GC churn of making new
1182             Rects only to drop them on the floor.
1183         */
1184         Rect pad = new Rect();
1185 
1186         // Special stuff for compatibility mode: if the target density is not
1187         // the same as the display density, but the resource -is- the same as
1188         // the display density, then don't scale it down to the target density.
1189         // This allows us to load the system's density-correct resources into
1190         // an application in compatibility mode, without scaling those down
1191         // to the compatibility density only to have them scaled back up when
1192         // drawn to the screen.
1193         if (opts == null) opts = new BitmapFactory.Options();
1194         opts.inScreenDensity = Drawable.resolveDensity(res, 0);
1195         Bitmap  bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts);
1196         if (bm != null) {
1197             byte[] np = bm.getNinePatchChunk();
1198             if (np == null || !NinePatch.isNinePatchChunk(np)) {
1199                 np = null;
1200                 pad = null;
1201             }
1202 
1203             final Rect opticalInsets = new Rect();
1204             bm.getOpticalInsets(opticalInsets);
1205             return drawableFromBitmap(res, bm, np, pad, opticalInsets, srcName);
1206         }
1207         return null;
1208     }
1209 
1210     /**
1211      * Create a drawable from an XML document. For more information on how to
1212      * create resources in XML, see
1213      * <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
1214      */
1215     @NonNull
createFromXml(@onNull Resources r, @NonNull XmlPullParser parser)1216     public static Drawable createFromXml(@NonNull Resources r, @NonNull XmlPullParser parser)
1217             throws XmlPullParserException, IOException {
1218         return createFromXml(r, parser, null);
1219     }
1220 
1221     /**
1222      * Create a drawable from an XML document using an optional {@link Theme}.
1223      * For more information on how to create resources in XML, see
1224      * <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
1225      */
1226     @NonNull
createFromXml(@onNull Resources r, @NonNull XmlPullParser parser, @Nullable Theme theme)1227     public static Drawable createFromXml(@NonNull Resources r, @NonNull XmlPullParser parser,
1228             @Nullable Theme theme) throws XmlPullParserException, IOException {
1229         return createFromXmlForDensity(r, parser, 0, theme);
1230     }
1231 
1232     /**
1233      * Version of {@link #createFromXml(Resources, XmlPullParser, Theme)} that accepts a density
1234      * override.
1235      * @hide
1236      */
1237     @NonNull
createFromXmlForDensity(@onNull Resources r, @NonNull XmlPullParser parser, int density, @Nullable Theme theme)1238     public static Drawable createFromXmlForDensity(@NonNull Resources r,
1239             @NonNull XmlPullParser parser, int density, @Nullable Theme theme)
1240             throws XmlPullParserException, IOException {
1241         AttributeSet attrs = Xml.asAttributeSet(parser);
1242 
1243         int type;
1244         //noinspection StatementWithEmptyBody
1245         while ((type=parser.next()) != XmlPullParser.START_TAG
1246                 && type != XmlPullParser.END_DOCUMENT) {
1247             // Empty loop.
1248         }
1249 
1250         if (type != XmlPullParser.START_TAG) {
1251             throw new XmlPullParserException("No start tag found");
1252         }
1253 
1254         Drawable drawable = createFromXmlInnerForDensity(r, parser, attrs, density, theme);
1255 
1256         if (drawable == null) {
1257             throw new RuntimeException("Unknown initial tag: " + parser.getName());
1258         }
1259 
1260         return drawable;
1261     }
1262 
1263     /**
1264      * Create from inside an XML document.  Called on a parser positioned at
1265      * a tag in an XML document, tries to create a Drawable from that tag.
1266      * Returns null if the tag is not a valid drawable.
1267      */
1268     @NonNull
createFromXmlInner(@onNull Resources r, @NonNull XmlPullParser parser, @NonNull AttributeSet attrs)1269     public static Drawable createFromXmlInner(@NonNull Resources r, @NonNull XmlPullParser parser,
1270             @NonNull AttributeSet attrs) throws XmlPullParserException, IOException {
1271         return createFromXmlInner(r, parser, attrs, null);
1272     }
1273 
1274     /**
1275      * Create a drawable from inside an XML document using an optional
1276      * {@link Theme}. Called on a parser positioned at a tag in an XML
1277      * document, tries to create a Drawable from that tag. Returns {@code null}
1278      * if the tag is not a valid drawable.
1279      */
1280     @NonNull
createFromXmlInner(@onNull Resources r, @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme)1281     public static Drawable createFromXmlInner(@NonNull Resources r, @NonNull XmlPullParser parser,
1282             @NonNull AttributeSet attrs, @Nullable Theme theme)
1283             throws XmlPullParserException, IOException {
1284         return createFromXmlInnerForDensity(r, parser, attrs, 0, theme);
1285     }
1286 
1287     /**
1288      * Version of {@link #createFromXmlInner(Resources, XmlPullParser, AttributeSet, Theme)} that
1289      * accepts an override density.
1290      */
1291     @NonNull
createFromXmlInnerForDensity(@onNull Resources r, @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, int density, @Nullable Theme theme)1292     static Drawable createFromXmlInnerForDensity(@NonNull Resources r,
1293             @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, int density,
1294             @Nullable Theme theme) throws XmlPullParserException, IOException {
1295         return r.getDrawableInflater().inflateFromXmlForDensity(parser.getName(), parser, attrs,
1296                 density, theme);
1297     }
1298 
1299     /**
1300      * Create a drawable from file path name.
1301      */
1302     @Nullable
createFromPath(String pathName)1303     public static Drawable createFromPath(String pathName) {
1304         if (pathName == null) {
1305             return null;
1306         }
1307 
1308         Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, pathName);
1309         try {
1310             Bitmap bm = BitmapFactory.decodeFile(pathName);
1311             if (bm != null) {
1312                 return drawableFromBitmap(null, bm, null, null, null, pathName);
1313             }
1314         } finally {
1315             Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
1316         }
1317 
1318         return null;
1319     }
1320 
1321     /**
1322      * Inflate this Drawable from an XML resource. Does not apply a theme.
1323      *
1324      * @see #inflate(Resources, XmlPullParser, AttributeSet, Theme)
1325      */
inflate(@onNull Resources r, @NonNull XmlPullParser parser, @NonNull AttributeSet attrs)1326     public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
1327             @NonNull AttributeSet attrs) throws XmlPullParserException, IOException {
1328         inflate(r, parser, attrs, null);
1329     }
1330 
1331     /**
1332      * Inflate this Drawable from an XML resource optionally styled by a theme.
1333      * This can't be called more than once for each Drawable. Note that framework may have called
1334      * this once to create the Drawable instance from XML resource.
1335      *
1336      * @param r Resources used to resolve attribute values
1337      * @param parser XML parser from which to inflate this Drawable
1338      * @param attrs Base set of attribute values
1339      * @param theme Theme to apply, may be null
1340      * @throws XmlPullParserException
1341      * @throws IOException
1342      */
inflate(@onNull Resources r, @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme)1343     public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
1344             @NonNull AttributeSet attrs, @Nullable Theme theme)
1345             throws XmlPullParserException, IOException {
1346         final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.Drawable);
1347         mVisible = a.getBoolean(R.styleable.Drawable_visible, mVisible);
1348         a.recycle();
1349     }
1350 
1351     /**
1352      * Inflate a Drawable from an XML resource.
1353      *
1354      * @throws XmlPullParserException
1355      * @throws IOException
1356      */
inflateWithAttributes(@onNull @uppressWarnings"unused") Resources r, @NonNull @SuppressWarnings("unused") XmlPullParser parser, @NonNull TypedArray attrs, @AttrRes int visibleAttr)1357     void inflateWithAttributes(@NonNull @SuppressWarnings("unused") Resources r,
1358             @NonNull @SuppressWarnings("unused") XmlPullParser parser, @NonNull TypedArray attrs,
1359             @AttrRes int visibleAttr) throws XmlPullParserException, IOException {
1360         mVisible = attrs.getBoolean(visibleAttr, mVisible);
1361     }
1362 
1363     /**
1364      * Sets the source override density for this Drawable. If non-zero, this density is to be used
1365      * for any calls to {@link Resources#getDrawableForDensity(int, int, Theme)} or
1366      * {@link Resources#getValueForDensity(int, int, TypedValue, boolean)}.
1367      * @hide
1368      */
setSrcDensityOverride(int density)1369     final void setSrcDensityOverride(int density) {
1370         mSrcDensityOverride = density;
1371     }
1372 
1373     /**
1374      * This abstract class is used by {@link Drawable}s to store shared constant state and data
1375      * between Drawables. {@link BitmapDrawable}s created from the same resource will for instance
1376      * share a unique bitmap stored in their ConstantState.
1377      *
1378      * <p>
1379      * {@link #newDrawable(Resources)} can be used as a factory to create new Drawable instances
1380      * from this ConstantState.
1381      * </p>
1382      *
1383      * Use {@link Drawable#getConstantState()} to retrieve the ConstantState of a Drawable. Calling
1384      * {@link Drawable#mutate()} on a Drawable should typically create a new ConstantState for that
1385      * Drawable.
1386      */
1387     public static abstract class ConstantState {
1388         /**
1389          * Creates a new Drawable instance from its constant state.
1390          * <p>
1391          * <strong>Note:</strong> Using this method means density-dependent
1392          * properties, such as pixel dimensions or bitmap images, will not be
1393          * updated to match the density of the target display. To ensure
1394          * correct scaling, use {@link #newDrawable(Resources)} instead to
1395          * provide an appropriate Resources object.
1396          *
1397          * @return a new drawable object based on this constant state
1398          * @see #newDrawable(Resources)
1399          */
newDrawable()1400         public abstract @NonNull Drawable newDrawable();
1401 
1402         /**
1403          * Creates a new Drawable instance from its constant state using the
1404          * specified resources. This method should be implemented for drawables
1405          * that have density-dependent properties.
1406          * <p>
1407          * The default implementation for this method calls through to
1408          * {@link #newDrawable()}.
1409          *
1410          * @param res the resources of the context in which the drawable will
1411          *            be displayed
1412          * @return a new drawable object based on this constant state
1413          */
newDrawable(@ullable Resources res)1414         public @NonNull Drawable newDrawable(@Nullable Resources res) {
1415             return newDrawable();
1416         }
1417 
1418         /**
1419          * Creates a new Drawable instance from its constant state using the
1420          * specified resources and theme. This method should be implemented for
1421          * drawables that have theme-dependent properties.
1422          * <p>
1423          * The default implementation for this method calls through to
1424          * {@link #newDrawable(Resources)}.
1425          *
1426          * @param res the resources of the context in which the drawable will
1427          *            be displayed
1428          * @param theme the theme of the context in which the drawable will be
1429          *              displayed
1430          * @return a new drawable object based on this constant state
1431          */
newDrawable(@ullable Resources res, @Nullable @SuppressWarnings("unused") Theme theme)1432         public @NonNull Drawable newDrawable(@Nullable Resources res,
1433                 @Nullable @SuppressWarnings("unused") Theme theme) {
1434             return newDrawable(res);
1435         }
1436 
1437         /**
1438          * Return a bit mask of configuration changes that will impact
1439          * this drawable (and thus require completely reloading it).
1440          */
getChangingConfigurations()1441         public abstract @Config int getChangingConfigurations();
1442 
1443         /**
1444          * Return whether this constant state can have a theme applied.
1445          */
canApplyTheme()1446         public boolean canApplyTheme() {
1447             return false;
1448         }
1449     }
1450 
1451     /**
1452      * Return a {@link ConstantState} instance that holds the shared state of this Drawable.
1453      *
1454      * @return The ConstantState associated to that Drawable.
1455      * @see ConstantState
1456      * @see Drawable#mutate()
1457      */
getConstantState()1458     public @Nullable ConstantState getConstantState() {
1459         return null;
1460     }
1461 
drawableFromBitmap(Resources res, Bitmap bm, byte[] np, Rect pad, Rect layoutBounds, String srcName)1462     private static Drawable drawableFromBitmap(Resources res, Bitmap bm, byte[] np,
1463             Rect pad, Rect layoutBounds, String srcName) {
1464 
1465         if (np != null) {
1466             return new NinePatchDrawable(res, bm, np, pad, layoutBounds, srcName);
1467         }
1468 
1469         return new BitmapDrawable(res, bm);
1470     }
1471 
1472     /**
1473      * Ensures the tint filter is consistent with the current tint color and
1474      * mode.
1475      */
updateTintFilter(@ullable PorterDuffColorFilter tintFilter, @Nullable ColorStateList tint, @Nullable PorterDuff.Mode tintMode)1476     @Nullable PorterDuffColorFilter updateTintFilter(@Nullable PorterDuffColorFilter tintFilter,
1477             @Nullable ColorStateList tint, @Nullable PorterDuff.Mode tintMode) {
1478         if (tint == null || tintMode == null) {
1479             return null;
1480         }
1481 
1482         final int color = tint.getColorForState(getState(), Color.TRANSPARENT);
1483         if (tintFilter == null) {
1484             return new PorterDuffColorFilter(color, tintMode);
1485         }
1486 
1487         tintFilter.setColor(color);
1488         tintFilter.setMode(tintMode);
1489         return tintFilter;
1490     }
1491 
1492     /**
1493      * Obtains styled attributes from the theme, if available, or unstyled
1494      * resources if the theme is null.
1495      * @hide
1496      */
obtainAttributes(@onNull Resources res, @Nullable Theme theme, @NonNull AttributeSet set, @NonNull int[] attrs)1497     protected static @NonNull TypedArray obtainAttributes(@NonNull Resources res,
1498             @Nullable Theme theme, @NonNull AttributeSet set, @NonNull int[] attrs) {
1499         if (theme == null) {
1500             return res.obtainAttributes(set, attrs);
1501         }
1502         return theme.obtainStyledAttributes(set, attrs, 0, 0);
1503     }
1504 
1505     /**
1506      * Scales a floating-point pixel value from the source density to the
1507      * target density.
1508      *
1509      * @param pixels the pixel value for use in source density
1510      * @param sourceDensity the source density
1511      * @param targetDensity the target density
1512      * @return the scaled pixel value for use in target density
1513      */
scaleFromDensity(float pixels, int sourceDensity, int targetDensity)1514     static float scaleFromDensity(float pixels, int sourceDensity, int targetDensity) {
1515         return pixels * targetDensity / sourceDensity;
1516     }
1517 
1518     /**
1519      * Scales a pixel value from the source density to the target density,
1520      * optionally handling the resulting pixel value as a size rather than an
1521      * offset.
1522      * <p>
1523      * A size conversion involves rounding the base value and ensuring that
1524      * a non-zero base value is at least one pixel in size.
1525      * <p>
1526      * An offset conversion involves simply truncating the base value to an
1527      * integer.
1528      *
1529      * @param pixels the pixel value for use in source density
1530      * @param sourceDensity the source density
1531      * @param targetDensity the target density
1532      * @param isSize {@code true} to handle the resulting scaled value as a
1533      *               size, or {@code false} to handle it as an offset
1534      * @return the scaled pixel value for use in target density
1535      */
scaleFromDensity( int pixels, int sourceDensity, int targetDensity, boolean isSize)1536     static int scaleFromDensity(
1537             int pixels, int sourceDensity, int targetDensity, boolean isSize) {
1538         if (pixels == 0 || sourceDensity == targetDensity) {
1539             return pixels;
1540         }
1541 
1542         final float result = pixels * targetDensity / (float) sourceDensity;
1543         if (!isSize) {
1544             return (int) result;
1545         }
1546 
1547         final int rounded = Math.round(result);
1548         if (rounded != 0) {
1549             return rounded;
1550         } else if (pixels > 0) {
1551             return 1;
1552         } else {
1553             return -1;
1554         }
1555     }
1556 
resolveDensity(@ullable Resources r, int parentDensity)1557     static int resolveDensity(@Nullable Resources r, int parentDensity) {
1558         final int densityDpi = r == null ? parentDensity : r.getDisplayMetrics().densityDpi;
1559         return densityDpi == 0 ? DisplayMetrics.DENSITY_DEFAULT : densityDpi;
1560     }
1561 
1562     /**
1563      * Re-throws an exception as a {@link RuntimeException} with an empty stack
1564      * trace to avoid cluttering the log. The original exception's stack trace
1565      * will still be included.
1566      *
1567      * @param cause the exception to re-throw
1568      * @throws RuntimeException
1569      */
rethrowAsRuntimeException(@onNull Exception cause)1570     static void rethrowAsRuntimeException(@NonNull Exception cause) throws RuntimeException {
1571         final RuntimeException e = new RuntimeException(cause);
1572         e.setStackTrace(new StackTraceElement[0]);
1573         throw e;
1574     }
1575 
1576     /**
1577      * Parses a {@link android.graphics.PorterDuff.Mode} from a tintMode
1578      * attribute's enum value.
1579      *
1580      * @hide
1581      */
parseTintMode(int value, Mode defaultMode)1582     public static PorterDuff.Mode parseTintMode(int value, Mode defaultMode) {
1583         switch (value) {
1584             case 3: return Mode.SRC_OVER;
1585             case 5: return Mode.SRC_IN;
1586             case 9: return Mode.SRC_ATOP;
1587             case 14: return Mode.MULTIPLY;
1588             case 15: return Mode.SCREEN;
1589             case 16: return Mode.ADD;
1590             default: return defaultMode;
1591         }
1592     }
1593 }
1594 
1595