19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 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 198e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viveretteimport com.android.internal.R; 208e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParser; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 24a12962207155305da44b5a1b8fb9acaed358c14cAlan Viveretteimport android.annotation.NonNull; 257e3ede288926bdfb79b1571fed74cad614935821Alan Viveretteimport android.annotation.Nullable; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources; 2752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viveretteimport android.content.res.Resources.Theme; 28a12962207155305da44b5a1b8fb9acaed358c14cAlan Viveretteimport android.content.res.TypedArray; 297e3ede288926bdfb79b1571fed74cad614935821Alan Viveretteimport android.graphics.Bitmap; 300bece71ee24f75967b86de47cae07e6fc04b4b36Alan Viveretteimport android.graphics.Insets; 310bece71ee24f75967b86de47cae07e6fc04b4b36Alan Viveretteimport android.graphics.Outline; 326dfa60f33ca6018959ebff1efde82db7d2aed1e3Alan Viveretteimport android.graphics.PixelFormat; 330bece71ee24f75967b86de47cae07e6fc04b4b36Alan Viveretteimport android.graphics.Rect; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 357e3ede288926bdfb79b1571fed74cad614935821Alan Viveretteimport android.util.DisplayMetrics; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A Drawable that insets another Drawable by a specified distance. 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is used when a View needs a background that is smaller than 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the View's actual bounds. 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 44dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * <p>It can be defined in an XML file with the <code><inset></code> element. For more 45dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * information, see the guide to <a 46dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p> 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#InsetDrawable_visible 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#InsetDrawable_drawable 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#InsetDrawable_insetLeft 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#InsetDrawable_insetRight 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#InsetDrawable_insetTop 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#InsetDrawable_insetBottom 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 55a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverettepublic class InsetDrawable extends DrawableWrapper { 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Rect mTmpRect = new Rect(); 578e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette 58f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette private InsetState mState; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 60f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette /** 61f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette * No-arg constructor used by drawable inflation. 62f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette */ 63f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette InsetDrawable() { 647e3ede288926bdfb79b1571fed74cad614935821Alan Viverette this(new InsetState(null, null), null); 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 67f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette /** 68f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette * Creates a new inset drawable with the specified inset. 69f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette * 70f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette * @param drawable The drawable to inset. 71f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette * @param inset Inset in pixels around the drawable. 72f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette */ 737e3ede288926bdfb79b1571fed74cad614935821Alan Viverette public InsetDrawable(@Nullable Drawable drawable, int inset) { 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(drawable, inset, inset, inset, inset); 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 77f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette /** 78f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette * Creates a new inset drawable with the specified insets. 79f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette * 80f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette * @param drawable The drawable to inset. 81f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette * @param insetLeft Left inset in pixels. 82f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette * @param insetTop Top inset in pixels. 83f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette * @param insetRight Right inset in pixels. 84f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette * @param insetBottom Bottom inset in pixels. 85f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette */ 867e3ede288926bdfb79b1571fed74cad614935821Alan Viverette public InsetDrawable(@Nullable Drawable drawable, int insetLeft, int insetTop, 877e3ede288926bdfb79b1571fed74cad614935821Alan Viverette int insetRight, int insetBottom) { 887e3ede288926bdfb79b1571fed74cad614935821Alan Viverette this(new InsetState(null, null), null); 89b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette 90d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette mState.mInsetLeft = insetLeft; 91d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette mState.mInsetTop = insetTop; 92d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette mState.mInsetRight = insetRight; 93d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette mState.mInsetBottom = insetBottom; 94b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette 95a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette setDrawable(drawable); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 9852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette @Override 997e3ede288926bdfb79b1571fed74cad614935821Alan Viverette public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser, 1007e3ede288926bdfb79b1571fed74cad614935821Alan Viverette @NonNull AttributeSet attrs, @Nullable Theme theme) 10152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette throws XmlPullParserException, IOException { 1027e3ede288926bdfb79b1571fed74cad614935821Alan Viverette final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.InsetDrawable); 1037e3ede288926bdfb79b1571fed74cad614935821Alan Viverette 1047e3ede288926bdfb79b1571fed74cad614935821Alan Viverette // Inflation will advance the XmlPullParser and AttributeSet. 105a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette super.inflate(r, parser, attrs, theme); 106014e14b242848eaa86a10562e1c494143a0149aaChet Haase 1078e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette updateStateFromTypedArray(a); 108d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette verifyRequiredAttributes(a); 109d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette a.recycle(); 110d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette } 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 112a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette @Override 1137e3ede288926bdfb79b1571fed74cad614935821Alan Viverette public void applyTheme(@NonNull Theme t) { 1147e3ede288926bdfb79b1571fed74cad614935821Alan Viverette super.applyTheme(t); 1158e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette 116d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette final InsetState state = mState; 11717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette if (state == null) { 1188e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette return; 1198e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette } 1208e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette 12117cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette if (state.mThemeAttrs != null) { 12217cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.InsetDrawable); 12317cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette try { 12417cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette updateStateFromTypedArray(a); 12517cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette verifyRequiredAttributes(a); 12617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette } catch (XmlPullParserException e) { 127c078c605ab904b0e4a5d793cbeffd78c340f2816Alan Viverette rethrowAsRuntimeException(e); 12817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette } finally { 12917cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette a.recycle(); 13017cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette } 13117cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette } 1327e3ede288926bdfb79b1571fed74cad614935821Alan Viverette } 13317cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette 1347e3ede288926bdfb79b1571fed74cad614935821Alan Viverette private void verifyRequiredAttributes(@NonNull TypedArray a) throws XmlPullParserException { 1357e3ede288926bdfb79b1571fed74cad614935821Alan Viverette // If we're not waiting on a theme, verify required attributes. 1367e3ede288926bdfb79b1571fed74cad614935821Alan Viverette if (getDrawable() == null && (mState.mThemeAttrs == null 1377e3ede288926bdfb79b1571fed74cad614935821Alan Viverette || mState.mThemeAttrs[R.styleable.InsetDrawable_drawable] == 0)) { 1387e3ede288926bdfb79b1571fed74cad614935821Alan Viverette throw new XmlPullParserException(a.getPositionDescription() 1397e3ede288926bdfb79b1571fed74cad614935821Alan Viverette + ": <inset> tag requires a 'drawable' attribute or " 1407e3ede288926bdfb79b1571fed74cad614935821Alan Viverette + "child tag defining a drawable"); 1417e3ede288926bdfb79b1571fed74cad614935821Alan Viverette } 1427e3ede288926bdfb79b1571fed74cad614935821Alan Viverette } 1437e3ede288926bdfb79b1571fed74cad614935821Alan Viverette 1447e3ede288926bdfb79b1571fed74cad614935821Alan Viverette private void updateStateFromTypedArray(@NonNull TypedArray a) { 1457e3ede288926bdfb79b1571fed74cad614935821Alan Viverette final InsetState state = mState; 1467e3ede288926bdfb79b1571fed74cad614935821Alan Viverette if (state == null) { 1477e3ede288926bdfb79b1571fed74cad614935821Alan Viverette return; 1487e3ede288926bdfb79b1571fed74cad614935821Alan Viverette } 1497e3ede288926bdfb79b1571fed74cad614935821Alan Viverette 1507e3ede288926bdfb79b1571fed74cad614935821Alan Viverette // Account for any configuration changes. 1517e3ede288926bdfb79b1571fed74cad614935821Alan Viverette state.mChangingConfigurations |= a.getChangingConfigurations(); 1527e3ede288926bdfb79b1571fed74cad614935821Alan Viverette 1537e3ede288926bdfb79b1571fed74cad614935821Alan Viverette // Extract the theme attributes, if any. 1547e3ede288926bdfb79b1571fed74cad614935821Alan Viverette state.mThemeAttrs = a.extractThemeAttrs(); 1557e3ede288926bdfb79b1571fed74cad614935821Alan Viverette 1567e3ede288926bdfb79b1571fed74cad614935821Alan Viverette // Inset attribute may be overridden by more specific attributes. 1577e3ede288926bdfb79b1571fed74cad614935821Alan Viverette if (a.hasValue(R.styleable.InsetDrawable_inset)) { 1587e3ede288926bdfb79b1571fed74cad614935821Alan Viverette final int inset = a.getDimensionPixelOffset(R.styleable.InsetDrawable_inset, 0); 1597e3ede288926bdfb79b1571fed74cad614935821Alan Viverette state.mInsetLeft = inset; 1607e3ede288926bdfb79b1571fed74cad614935821Alan Viverette state.mInsetTop = inset; 1617e3ede288926bdfb79b1571fed74cad614935821Alan Viverette state.mInsetRight = inset; 1627e3ede288926bdfb79b1571fed74cad614935821Alan Viverette state.mInsetBottom = inset; 1637e3ede288926bdfb79b1571fed74cad614935821Alan Viverette } 1647e3ede288926bdfb79b1571fed74cad614935821Alan Viverette 1657e3ede288926bdfb79b1571fed74cad614935821Alan Viverette state.mInsetLeft = a.getDimensionPixelOffset( 1667e3ede288926bdfb79b1571fed74cad614935821Alan Viverette R.styleable.InsetDrawable_insetLeft, state.mInsetLeft); 1677e3ede288926bdfb79b1571fed74cad614935821Alan Viverette state.mInsetRight = a.getDimensionPixelOffset( 1687e3ede288926bdfb79b1571fed74cad614935821Alan Viverette R.styleable.InsetDrawable_insetRight, state.mInsetRight); 1697e3ede288926bdfb79b1571fed74cad614935821Alan Viverette state.mInsetTop = a.getDimensionPixelOffset( 1707e3ede288926bdfb79b1571fed74cad614935821Alan Viverette R.styleable.InsetDrawable_insetTop, state.mInsetTop); 1717e3ede288926bdfb79b1571fed74cad614935821Alan Viverette state.mInsetBottom = a.getDimensionPixelOffset( 1727e3ede288926bdfb79b1571fed74cad614935821Alan Viverette R.styleable.InsetDrawable_insetBottom, state.mInsetBottom); 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 174b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean getPadding(Rect padding) { 177a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette final boolean pad = super.getPadding(padding); 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette padding.left += mState.mInsetLeft; 180d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette padding.right += mState.mInsetRight; 181d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette padding.top += mState.mInsetTop; 182d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette padding.bottom += mState.mInsetBottom; 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 184f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette return pad || (mState.mInsetLeft | mState.mInsetRight 185f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette | mState.mInsetTop | mState.mInsetBottom) != 0; 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 188c054966b719c8a7255f7cf4120cca5050acb68bdAlan Viverette /** @hide */ 189c054966b719c8a7255f7cf4120cca5050acb68bdAlan Viverette @Override 190c054966b719c8a7255f7cf4120cca5050acb68bdAlan Viverette public Insets getOpticalInsets() { 191c054966b719c8a7255f7cf4120cca5050acb68bdAlan Viverette final Insets contentInsets = super.getOpticalInsets(); 192d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette return Insets.of(contentInsets.left + mState.mInsetLeft, 193d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette contentInsets.top + mState.mInsetTop, 194d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette contentInsets.right + mState.mInsetRight, 195d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette contentInsets.bottom + mState.mInsetBottom); 196c054966b719c8a7255f7cf4120cca5050acb68bdAlan Viverette } 197c054966b719c8a7255f7cf4120cca5050acb68bdAlan Viverette 19887980f9a7383fa4150f9c037ed34c37677f97f97Alan Viverette @Override 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getOpacity() { 2006dfa60f33ca6018959ebff1efde82db7d2aed1e3Alan Viverette final InsetState state = mState; 201a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette final int opacity = getDrawable().getOpacity(); 2026dfa60f33ca6018959ebff1efde82db7d2aed1e3Alan Viverette if (opacity == PixelFormat.OPAQUE && (state.mInsetLeft > 0 || state.mInsetTop > 0 2036dfa60f33ca6018959ebff1efde82db7d2aed1e3Alan Viverette || state.mInsetRight > 0 || state.mInsetBottom > 0)) { 2046dfa60f33ca6018959ebff1efde82db7d2aed1e3Alan Viverette return PixelFormat.TRANSLUCENT; 2056dfa60f33ca6018959ebff1efde82db7d2aed1e3Alan Viverette } 2066dfa60f33ca6018959ebff1efde82db7d2aed1e3Alan Viverette return opacity; 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 208b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onBoundsChange(Rect bounds) { 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Rect r = mTmpRect; 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project r.set(bounds); 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 214d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette r.left += mState.mInsetLeft; 215d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette r.top += mState.mInsetTop; 216d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette r.right -= mState.mInsetRight; 217d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette r.bottom -= mState.mInsetBottom; 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 219a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette // Apply inset bounds to the wrapped drawable. 220a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette super.onBoundsChange(r); 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getIntrinsicWidth() { 22576165b2a4bc3b618bdfa9e4286d405892b68f122Alan Viverette final int childWidth = getDrawable().getIntrinsicWidth(); 22676165b2a4bc3b618bdfa9e4286d405892b68f122Alan Viverette if (childWidth < 0) { 22776165b2a4bc3b618bdfa9e4286d405892b68f122Alan Viverette return -1; 22876165b2a4bc3b618bdfa9e4286d405892b68f122Alan Viverette } 22976165b2a4bc3b618bdfa9e4286d405892b68f122Alan Viverette return childWidth + mState.mInsetLeft + mState.mInsetRight; 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getIntrinsicHeight() { 23476165b2a4bc3b618bdfa9e4286d405892b68f122Alan Viverette final int childHeight = getDrawable().getIntrinsicHeight(); 23576165b2a4bc3b618bdfa9e4286d405892b68f122Alan Viverette if (childHeight < 0) { 23676165b2a4bc3b618bdfa9e4286d405892b68f122Alan Viverette return -1; 23776165b2a4bc3b618bdfa9e4286d405892b68f122Alan Viverette } 23876165b2a4bc3b618bdfa9e4286d405892b68f122Alan Viverette return childHeight + mState.mInsetTop + mState.mInsetBottom; 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 24231ba192dd201df2cad96a8c503f730130ab0d80fChris Craik public void getOutline(@NonNull Outline outline) { 243a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette getDrawable().getOutline(outline); 2443e1585e05ddb0fd60033a5603e330b8ab1f69303Chris Craik } 2453e1585e05ddb0fd60033a5603e330b8ab1f69303Chris Craik 2463e1585e05ddb0fd60033a5603e330b8ab1f69303Chris Craik @Override 247a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette DrawableWrapperState mutateConstantState() { 2487e3ede288926bdfb79b1571fed74cad614935821Alan Viverette mState = new InsetState(mState, null); 249a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette return mState; 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 252a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette static final class InsetState extends DrawableWrapper.DrawableWrapperState { 2537e3ede288926bdfb79b1571fed74cad614935821Alan Viverette private int[] mThemeAttrs; 2547e3ede288926bdfb79b1571fed74cad614935821Alan Viverette 255d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette int mInsetLeft = 0; 256d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette int mInsetTop = 0; 257d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette int mInsetRight = 0; 258d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette int mInsetBottom = 0; 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2607e3ede288926bdfb79b1571fed74cad614935821Alan Viverette InsetState(@Nullable InsetState orig, @Nullable Resources res) { 2617e3ede288926bdfb79b1571fed74cad614935821Alan Viverette super(orig, res); 262a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (orig != null) { 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInsetLeft = orig.mInsetLeft; 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInsetTop = orig.mInsetTop; 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInsetRight = orig.mInsetRight; 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInsetBottom = orig.mInsetBottom; 2687e3ede288926bdfb79b1571fed74cad614935821Alan Viverette 2697e3ede288926bdfb79b1571fed74cad614935821Alan Viverette if (orig.mDensity != mDensity) { 2707e3ede288926bdfb79b1571fed74cad614935821Alan Viverette applyDensityScaling(orig.mDensity, mDensity); 2717e3ede288926bdfb79b1571fed74cad614935821Alan Viverette } 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2767e3ede288926bdfb79b1571fed74cad614935821Alan Viverette void onDensityChanged(int sourceDensity, int targetDensity) { 2777e3ede288926bdfb79b1571fed74cad614935821Alan Viverette super.onDensityChanged(sourceDensity, targetDensity); 2787e3ede288926bdfb79b1571fed74cad614935821Alan Viverette 2797e3ede288926bdfb79b1571fed74cad614935821Alan Viverette applyDensityScaling(sourceDensity, targetDensity); 2807e3ede288926bdfb79b1571fed74cad614935821Alan Viverette } 2817e3ede288926bdfb79b1571fed74cad614935821Alan Viverette 2827e3ede288926bdfb79b1571fed74cad614935821Alan Viverette /** 2837e3ede288926bdfb79b1571fed74cad614935821Alan Viverette * Called when the constant state density changes to scale 2847e3ede288926bdfb79b1571fed74cad614935821Alan Viverette * density-dependent properties specific to insets. 2857e3ede288926bdfb79b1571fed74cad614935821Alan Viverette * 2867e3ede288926bdfb79b1571fed74cad614935821Alan Viverette * @param sourceDensity the previous constant state density 2877e3ede288926bdfb79b1571fed74cad614935821Alan Viverette * @param targetDensity the new constant state density 2887e3ede288926bdfb79b1571fed74cad614935821Alan Viverette */ 2897e3ede288926bdfb79b1571fed74cad614935821Alan Viverette private void applyDensityScaling(int sourceDensity, int targetDensity) { 2907e3ede288926bdfb79b1571fed74cad614935821Alan Viverette mInsetLeft = Bitmap.scaleFromDensity(mInsetLeft, sourceDensity, targetDensity); 2917e3ede288926bdfb79b1571fed74cad614935821Alan Viverette mInsetTop = Bitmap.scaleFromDensity(mInsetTop, sourceDensity, targetDensity); 2927e3ede288926bdfb79b1571fed74cad614935821Alan Viverette mInsetRight = Bitmap.scaleFromDensity(mInsetRight, sourceDensity, targetDensity); 2937e3ede288926bdfb79b1571fed74cad614935821Alan Viverette mInsetBottom = Bitmap.scaleFromDensity(mInsetBottom, sourceDensity, targetDensity); 2947e3ede288926bdfb79b1571fed74cad614935821Alan Viverette } 2957e3ede288926bdfb79b1571fed74cad614935821Alan Viverette 2967e3ede288926bdfb79b1571fed74cad614935821Alan Viverette @Override 2977e3ede288926bdfb79b1571fed74cad614935821Alan Viverette public Drawable newDrawable(@Nullable Resources res) { 2987e3ede288926bdfb79b1571fed74cad614935821Alan Viverette // If this drawable is being created for a different density, 2997e3ede288926bdfb79b1571fed74cad614935821Alan Viverette // just create a new constant state and call it a day. 3007e3ede288926bdfb79b1571fed74cad614935821Alan Viverette final InsetState state; 3017e3ede288926bdfb79b1571fed74cad614935821Alan Viverette if (res != null) { 3027e3ede288926bdfb79b1571fed74cad614935821Alan Viverette final int densityDpi = res.getDisplayMetrics().densityDpi; 3037e3ede288926bdfb79b1571fed74cad614935821Alan Viverette final int density = densityDpi == 0 ? DisplayMetrics.DENSITY_DEFAULT : densityDpi; 3047e3ede288926bdfb79b1571fed74cad614935821Alan Viverette if (density != mDensity) { 3057e3ede288926bdfb79b1571fed74cad614935821Alan Viverette state = new InsetState(this, res); 3067e3ede288926bdfb79b1571fed74cad614935821Alan Viverette } else { 3077e3ede288926bdfb79b1571fed74cad614935821Alan Viverette state = this; 3087e3ede288926bdfb79b1571fed74cad614935821Alan Viverette } 3097e3ede288926bdfb79b1571fed74cad614935821Alan Viverette } else { 3107e3ede288926bdfb79b1571fed74cad614935821Alan Viverette state = this; 3117e3ede288926bdfb79b1571fed74cad614935821Alan Viverette } 3127e3ede288926bdfb79b1571fed74cad614935821Alan Viverette 3137e3ede288926bdfb79b1571fed74cad614935821Alan Viverette return new InsetDrawable(state, res); 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 317f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette /** 318f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette * The one constructor to rule them all. This is called by all public 319f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette * constructors to set the state and initialize local properties. 320f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette */ 3217e3ede288926bdfb79b1571fed74cad614935821Alan Viverette private InsetDrawable(@NonNull InsetState state, @Nullable Resources res) { 322a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette super(state, res); 323f0f7f8ceb5d1effd34fe2734f6493726bf01dd1cAlan Viverette 324a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette mState = state; 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 328