DrawableWrapper.java revision bd3bfc5285dcacff0a69fecf3baeeeb90d887a58
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2015 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.graphics.drawable; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParser; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.annotation.NonNull; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.annotation.Nullable; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.ColorStateList; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Bitmap; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.ColorFilter; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Insets; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Outline; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.PixelFormat; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.PorterDuff; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Collection; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Drawable container with only one child element. 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class DrawableWrapper extends Drawable implements Drawable.Callback { 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private DrawableWrapperState mState; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mDrawable; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mMutated; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DrawableWrapper(DrawableWrapperState state, Resources res) { 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = state; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateLocalState(res); 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a new wrapper around the specified drawable. 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param dr the drawable to wrap 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public DrawableWrapper(@Nullable Drawable dr) { 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = null; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDrawable = dr; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Initializes local dynamic properties from state. This should be called 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * after significant state changes, e.g. from the One True Constructor and 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * after inflating or applying a theme. 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void updateLocalState(Resources res) { 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != null && mState.mDrawableState != null) { 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Drawable dr = mState.mDrawableState.newDrawable(res); 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setDrawable(dr); 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the wrapped drawable. 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param dr the wrapped drawable 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setDrawable(@Nullable Drawable dr) { 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDrawable != null) { 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDrawable.setCallback(null); 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDrawable = dr; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dr != null) { 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dr.setCallback(this); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Only call setters for data that's stored in the base Drawable. 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dr.setVisible(isVisible(), true); 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dr.setState(getState()); 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dr.setLevel(getLevel()); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dr.setBounds(getBounds()); 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dr.setLayoutDirection(getLayoutDirection()); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != null) { 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.mDrawableState = dr.getConstantState(); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidateSelf(); 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1069461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 1079461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn /** 1089461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn * @return the wrapped drawable 1099461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn */ 1109461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn @Nullable 1119461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn public Drawable getDrawable() { 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDrawable; 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void updateStateFromTypedArray(TypedArray a) { 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final DrawableWrapperState state = mState; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state == null) { 1180d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn return; 1190d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn } 1200d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn 1210d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn // Account for any configuration changes. 1220d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn state.mChangingConfigurations |= a.getChangingConfigurations(); 1230d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn 1240d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn // Extract the theme attributes, if any. 1250d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn state.mThemeAttrs = a.extractThemeAttrs(); 1260d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn 1270d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn // TODO: Consider using R.styleable.DrawableWrapper_drawable 1280d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn } 1290d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn 1300d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn @Override 1310d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn public void applyTheme(Resources.Theme t) { 1320d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn super.applyTheme(t); 1330d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn 1340d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn final DrawableWrapperState state = mState; 1350d4b9c993d8f1108294f8ccb84eeacd92f051b50Dianne Hackborn if (state == null) { 136a3d487cb13983643d5024e493e4d56c96736f1ebDianne Hackborn return; 137a3d487cb13983643d5024e493e4d56c96736f1ebDianne Hackborn } 138a3d487cb13983643d5024e493e4d56c96736f1ebDianne Hackborn 139a3d487cb13983643d5024e493e4d56c96736f1ebDianne Hackborn if (mDrawable != null && mDrawable.canApplyTheme()) { 140a3d487cb13983643d5024e493e4d56c96736f1ebDianne Hackborn mDrawable.applyTheme(t); 141a3d487cb13983643d5024e493e4d56c96736f1ebDianne Hackborn } 142a3d487cb13983643d5024e493e4d56c96736f1ebDianne Hackborn } 143a3d487cb13983643d5024e493e4d56c96736f1ebDianne Hackborn 144a3d487cb13983643d5024e493e4d56c96736f1ebDianne Hackborn @Override 145a3d487cb13983643d5024e493e4d56c96736f1ebDianne Hackborn public boolean canApplyTheme() { 146a3d487cb13983643d5024e493e4d56c96736f1ebDianne Hackborn return (mState != null && mState.canApplyTheme()) || super.canApplyTheme(); 147a3d487cb13983643d5024e493e4d56c96736f1ebDianne Hackborn } 148a53de0629f3b94472c0f160f5bbe1090b020feabDianne Hackborn 149a53de0629f3b94472c0f160f5bbe1090b020feabDianne Hackborn @Override 150a53de0629f3b94472c0f160f5bbe1090b020feabDianne Hackborn public void invalidateDrawable(Drawable who) { 151a3d487cb13983643d5024e493e4d56c96736f1ebDianne Hackborn final Callback callback = getCallback(); 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (callback != null) { 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project callback.invalidateDrawable(this); 154d76ef97930d45e37dba4ac58b376c3067c2eb54aDirk Dougherty } 155d76ef97930d45e37dba4ac58b376c3067c2eb54aDirk Dougherty } 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 15886cbc2bf30a7623b2ad6564cf50ca20f87067ea7Dianne Hackborn public void scheduleDrawable(Drawable who, Runnable what, long when) { 15986cbc2bf30a7623b2ad6564cf50ca20f87067ea7Dianne Hackborn final Callback callback = getCallback(); 16086cbc2bf30a7623b2ad6564cf50ca20f87067ea7Dianne Hackborn if (callback != null) { 16186cbc2bf30a7623b2ad6564cf50ca20f87067ea7Dianne Hackborn callback.scheduleDrawable(this, what, when); 16286cbc2bf30a7623b2ad6564cf50ca20f87067ea7Dianne Hackborn } 16386cbc2bf30a7623b2ad6564cf50ca20f87067ea7Dianne Hackborn } 16486cbc2bf30a7623b2ad6564cf50ca20f87067ea7Dianne Hackborn 16586cbc2bf30a7623b2ad6564cf50ca20f87067ea7Dianne Hackborn @Override 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void unscheduleDrawable(Drawable who, Runnable what) { 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Callback callback = getCallback(); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (callback != null) { 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project callback.unscheduleDrawable(this, what); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void draw(@NonNull Canvas canvas) { 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDrawable != null) { 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDrawable.draw(canvas); 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getChangingConfigurations() { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.getChangingConfigurations() 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project | (mState != null ? mState.mChangingConfigurations : 0) 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project | mDrawable.getChangingConfigurations(); 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean getPadding(@NonNull Rect padding) { 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDrawable != null && mDrawable.getPadding(padding); 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @hide */ 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Insets getOpticalInsets() { 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDrawable != null ? mDrawable.getOpticalInsets() : Insets.NONE; 1969461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setHotspot(float x, float y) { 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDrawable != null) { 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDrawable.setHotspot(x, y); 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2049461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2069a84983a9fd9959671e102045eaf185b83291269Dianne Hackborn public void setHotspotBounds(int left, int top, int right, int bottom) { 2079a84983a9fd9959671e102045eaf185b83291269Dianne Hackborn if (mDrawable != null) { 2089a84983a9fd9959671e102045eaf185b83291269Dianne Hackborn mDrawable.setHotspotBounds(left, top, right, bottom); 2099a84983a9fd9959671e102045eaf185b83291269Dianne Hackborn } 2109a84983a9fd9959671e102045eaf185b83291269Dianne Hackborn } 2119a84983a9fd9959671e102045eaf185b83291269Dianne Hackborn 2129a84983a9fd9959671e102045eaf185b83291269Dianne Hackborn @Override 2139a84983a9fd9959671e102045eaf185b83291269Dianne Hackborn public void getHotspotBounds(@NonNull Rect outRect) { 2149a84983a9fd9959671e102045eaf185b83291269Dianne Hackborn if (mDrawable != null) { 2159a84983a9fd9959671e102045eaf185b83291269Dianne Hackborn mDrawable.getHotspotBounds(outRect); 2169461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } else { 2179461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn outRect.set(getBounds()); 2189461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 2199461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 2209461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 2219461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn @Override 2229461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn public boolean setVisible(boolean visible, boolean restart) { 223354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn final boolean superChanged = super.setVisible(visible, restart); 2249461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn final boolean changed = mDrawable != null && mDrawable.setVisible(visible, restart); 2259461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn return superChanged | changed; 2269461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn } 2279461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn 228354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn @Override 229354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn public void setAlpha(int alpha) { 2309461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn if (mDrawable != null) { 2319461b6f91f37fd32207da1bd734d9ea9629eb8e5Dianne Hackborn mDrawable.setAlpha(alpha); 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getAlpha() { 237334031cd07c3bd09d23fce0ebaf946fc6ecfee26Glenn Kasten return mDrawable != null ? mDrawable.getAlpha() : 255; 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setColorFilter(@Nullable ColorFilter colorFilter) { 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDrawable != null) { 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDrawable.setColorFilter(colorFilter); 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setTintList(@Nullable ColorStateList tint) { 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDrawable != null) { 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDrawable.setTintList(tint); 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setTintMode(@Nullable PorterDuff.Mode tintMode) { 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDrawable != null) { 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDrawable.setTintMode(tintMode); 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onLayoutDirectionChange(@View.ResolvedLayoutDir int layoutDirection) { 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDrawable != null && mDrawable.setLayoutDirection(layoutDirection); 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getOpacity() { 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDrawable != null ? mDrawable.getOpacity() : PixelFormat.TRANSPARENT; 2696098c5d3555860f272d8ddbd353a42f4c8474e1cJohn Spurlock } 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isStateful() { 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDrawable != null && mDrawable.isStateful(); 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected boolean onStateChange(int[] state) { 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDrawable != null) { 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean changed = mDrawable.setState(state); 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (changed) { 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onBoundsChange(getBounds()); 2826098c5d3555860f272d8ddbd353a42f4c8474e1cJohn Spurlock } 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return changed; 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2856098c5d3555860f272d8ddbd353a42f4c8474e1cJohn Spurlock return false; 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2886098c5d3555860f272d8ddbd353a42f4c8474e1cJohn Spurlock @Override 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected boolean onLevelChange(int level) { 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDrawable != null && mDrawable.setLevel(level); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onBoundsChange(@NonNull Rect bounds) { 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDrawable != null) { 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDrawable.setBounds(bounds); 297 } 298 } 299 300 @Override 301 public int getIntrinsicWidth() { 302 return mDrawable != null ? mDrawable.getIntrinsicWidth() : -1; 303 } 304 305 @Override 306 public int getIntrinsicHeight() { 307 return mDrawable != null ? mDrawable.getIntrinsicHeight() : -1; 308 } 309 310 @Override 311 public void getOutline(@NonNull Outline outline) { 312 if (mDrawable != null) { 313 mDrawable.getOutline(outline); 314 } else { 315 super.getOutline(outline); 316 } 317 } 318 319 @Override 320 @Nullable 321 public ConstantState getConstantState() { 322 if (mState != null && mState.canConstantState()) { 323 mState.mChangingConfigurations = getChangingConfigurations(); 324 return mState; 325 } 326 return null; 327 } 328 329 @Override 330 @NonNull 331 public Drawable mutate() { 332 if (!mMutated && super.mutate() == this) { 333 mState = mutateConstantState(); 334 if (mDrawable != null) { 335 mDrawable.mutate(); 336 } 337 if (mState != null) { 338 mState.mDrawableState = mDrawable != null ? mDrawable.getConstantState() : null; 339 } 340 mMutated = true; 341 } 342 return this; 343 } 344 345 /** 346 * Mutates the constant state and returns the new state. Responsible for 347 * updating any local copy. 348 * <p> 349 * This method should never call the super implementation; it should always 350 * mutate and return its own constant state. 351 * 352 * @return the new state 353 */ 354 DrawableWrapperState mutateConstantState() { 355 return mState; 356 } 357 358 /** 359 * @hide Only used by the framework for pre-loading resources. 360 */ 361 public void clearMutated() { 362 super.clearMutated(); 363 if (mDrawable != null) { 364 mDrawable.clearMutated(); 365 } 366 mMutated = false; 367 } 368 369 /** 370 * Called during inflation to inflate the child element. 371 */ 372 void inflateChildDrawable(Resources r, XmlPullParser parser, AttributeSet attrs, 373 Resources.Theme theme) throws XmlPullParserException, IOException { 374 // Drawable specified on the root element takes precedence. 375 if (getDrawable() != null) { 376 return; 377 } 378 379 // Seek to the first child element. 380 Drawable dr = null; 381 int type; 382 final int outerDepth = parser.getDepth(); 383 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 384 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 385 if (type == XmlPullParser.START_TAG) { 386 dr = Drawable.createFromXmlInner(r, parser, attrs, theme); 387 break; 388 } 389 } 390 391 if (dr != null) { 392 setDrawable(dr); 393 } 394 } 395 396 abstract static class DrawableWrapperState extends Drawable.ConstantState { 397 int[] mThemeAttrs; 398 int mChangingConfigurations; 399 400 Drawable.ConstantState mDrawableState; 401 402 DrawableWrapperState(DrawableWrapperState orig) { 403 if (orig != null) { 404 mThemeAttrs = orig.mThemeAttrs; 405 mChangingConfigurations = orig.mChangingConfigurations; 406 mDrawableState = orig.mDrawableState; 407 } 408 } 409 410 @Override 411 public boolean canApplyTheme() { 412 return mThemeAttrs != null 413 || (mDrawableState != null && mDrawableState.canApplyTheme()) 414 || super.canApplyTheme(); 415 } 416 417 @Override 418 public int addAtlasableBitmaps(Collection<Bitmap> atlasList) { 419 final Drawable.ConstantState state = mDrawableState; 420 if (state != null) { 421 return state.addAtlasableBitmaps(atlasList); 422 } 423 return 0; 424 } 425 426 @Override 427 public Drawable newDrawable() { 428 return newDrawable(null); 429 } 430 431 @Override 432 public abstract Drawable newDrawable(Resources res); 433 434 @Override 435 public int getChangingConfigurations() { 436 return mChangingConfigurations; 437 } 438 439 public boolean canConstantState() { 440 return mDrawableState != null; 441 } 442 } 443} 444