From e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1 Mon Sep 17 00:00:00 2001 From: Alan Viverette Date: Wed, 1 Apr 2015 13:10:18 -0700 Subject: [PATCH] Fix issues with theming of preloaded ColorStateLists Ensures changing configurations mask is propagated to the host drawable so that it can be properly cleared from cache on configuration changes. Also fixes constant state handling of the mask in the Inset and Rotate drawables. Hides new ColorStateList methods related to theming, since they should only be used during preloading or internally by framework drawables. Fixes bug where the cached versions of themeable ColorStateLists were modified by calling applyTheme() on the host drawable. Also cleans up some docs and naming in GradientDrawable. Bug: 19966397 Change-Id: I8c8d3cabbaf94b488c2b8fe9fd423e07d824c19c --- api/current.txt | 3 +- api/system-current.txt | 3 +- .../android/content/res/ColorStateList.java | 80 ++++++--- core/java/android/content/res/Resources.java | 17 +- .../drawable/AnimatedVectorDrawable.java | 2 +- .../graphics/drawable/BitmapDrawable.java | 9 +- .../graphics/drawable/ColorDrawable.java | 5 +- .../graphics/drawable/DrawableContainer.java | 6 +- .../graphics/drawable/DrawableWrapper.java | 5 +- .../graphics/drawable/GradientDrawable.java | 158 +++++++++--------- .../graphics/drawable/InsetDrawable.java | 14 -- .../graphics/drawable/LayerDrawable.java | 10 +- .../graphics/drawable/NinePatchDrawable.java | 7 +- .../graphics/drawable/RippleDrawable.java | 8 +- .../graphics/drawable/RotateDrawable.java | 3 - .../graphics/drawable/ShapeDrawable.java | 8 +- .../graphics/drawable/VectorDrawable.java | 7 +- 17 files changed, 193 insertions(+), 152 deletions(-) diff --git a/api/current.txt b/api/current.txt index eac30c1067dda..99dcc94d7a60c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -9441,11 +9441,10 @@ package android.content.res { public class ColorStateList implements android.os.Parcelable { ctor public ColorStateList(int[][], int[]); - method public void applyTheme(android.content.res.Resources.Theme); - method public boolean canApplyTheme(); method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public int describeContents(); + method public int getChangingConfigurations(); method public int getColorForState(int[], int); method public int getDefaultColor(); method public boolean isOpaque(); diff --git a/api/system-current.txt b/api/system-current.txt index 5e4c5f29b9937..b41308503a9c6 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -9727,11 +9727,10 @@ package android.content.res { public class ColorStateList implements android.os.Parcelable { ctor public ColorStateList(int[][], int[]); - method public void applyTheme(android.content.res.Resources.Theme); - method public boolean canApplyTheme(); method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public int describeContents(); + method public int getChangingConfigurations(); method public int getColorForState(int[], int); method public int getDefaultColor(); method public boolean isOpaque(); diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java index 7d8dff3c546b1..fdafb04c05253 100644 --- a/core/java/android/content/res/ColorStateList.java +++ b/core/java/android/content/res/ColorStateList.java @@ -71,10 +71,15 @@ import java.util.Arrays; */ public class ColorStateList implements Parcelable { private static final String TAG = "ColorStateList"; + private static final int DEFAULT_COLOR = Color.RED; private static final int[][] EMPTY = new int[][] { new int[0] }; - private static final SparseArray> sCache = - new SparseArray>(); + + /** Thread-safe cache of single-color ColorStateLists. */ + private static final SparseArray> sCache = new SparseArray<>(); + + /** Lazily-created factory for this color state list. */ + private ColorStateListFactory mFactory; private int[][] mThemeAttrs; private int mChangingConfigurations; @@ -125,7 +130,7 @@ public class ColorStateList implements Parcelable { } final ColorStateList csl = new ColorStateList(EMPTY, new int[] { color }); - sCache.put(color, new WeakReference(csl)); + sCache.put(color, new WeakReference<>(csl)); return csl; } } @@ -141,11 +146,13 @@ public class ColorStateList implements Parcelable { */ private ColorStateList(ColorStateList orig) { if (orig != null) { + mChangingConfigurations = orig.mChangingConfigurations; mStateSpecs = orig.mStateSpecs; mDefaultColor = orig.mDefaultColor; mIsOpaque = orig.mIsOpaque; - // Deep copy, this may change due to theming. + // Deep copy, these may change due to applyTheme(). + mThemeAttrs = orig.mThemeAttrs.clone(); mColors = orig.mColors.clone(); } } @@ -329,6 +336,7 @@ public class ColorStateList implements Parcelable { * attributes. * * @return whether a theme can be applied to this color state list + * @hide only for resource preloading */ public boolean canApplyTheme() { return mThemeAttrs != null; @@ -336,10 +344,15 @@ public class ColorStateList implements Parcelable { /** * Applies a theme to this color state list. + *

+ * Note: Applying a theme may affect the changing + * configuration parameters of this color state list. After calling this + * method, any dependent configurations must be updated by obtaining the + * new configuration mask from {@link #getChangingConfigurations()}. * * @param t the theme to apply */ - public void applyTheme(Theme t) { + private void applyTheme(Theme t) { if (mThemeAttrs == null) { return; } @@ -376,6 +389,38 @@ public class ColorStateList implements Parcelable { onColorsChanged(); } + /** + * Returns an appropriately themed color state list. + * + * @param t the theme to apply + * @return a copy of the color state list with the theme applied, or the + * color state list itself if there were no unresolved theme + * attributes + * @hide only for resource preloading + */ + public ColorStateList obtainForTheme(Theme t) { + if (t == null || !canApplyTheme()) { + return this; + } + + final ColorStateList clone = new ColorStateList(this); + clone.applyTheme(t); + return clone; + } + + /** + * Returns a mask of the configuration parameters for which this color + * state list may change, requiring that it be re-created. + * + * @return a mask of the changing configuration parameters, as defined by + * {@link android.content.pm.ActivityInfo} + * + * @see android.content.pm.ActivityInfo + */ + public int getChangingConfigurations() { + return mChangingConfigurations; + } + private int modulateColorAlpha(int baseColor, float alphaMod) { if (alphaMod == 1.0f) { return baseColor; @@ -383,8 +428,7 @@ public class ColorStateList implements Parcelable { final int baseAlpha = Color.alpha(baseColor); final int alpha = MathUtils.constrain((int) (baseAlpha * alphaMod + 0.5f), 0, 255); - final int color = (baseColor & 0xFFFFFF) | (alpha << 24); - return color; + return (baseColor & 0xFFFFFF) | (alpha << 24); } /** @@ -534,14 +578,18 @@ public class ColorStateList implements Parcelable { } /** - * @return A factory that can create new instances of this ColorStateList. + * @return a factory that can create new instances of this ColorStateList + * @hide only for resource preloading */ - ColorStateListFactory getFactory() { - return new ColorStateListFactory(this); + public ConstantState getConstantState() { + if (mFactory != null) { + mFactory = new ColorStateListFactory(this); + } + return mFactory; } - static class ColorStateListFactory extends ConstantState { - final ColorStateList mSrc; + private static class ColorStateListFactory extends ConstantState { + private final ColorStateList mSrc; public ColorStateListFactory(ColorStateList src) { mSrc = src; @@ -559,13 +607,7 @@ public class ColorStateList implements Parcelable { @Override public ColorStateList newInstance(Resources res, Theme theme) { - if (theme == null || !mSrc.canApplyTheme()) { - return mSrc; - } - - final ColorStateList clone = new ColorStateList(mSrc); - clone.applyTheme(theme); - return clone; + return mSrc.obtainForTheme(theme); } } diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 44018ffe0f38a..7ce3721e81bc7 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -41,7 +41,6 @@ import android.annotation.RawRes; import android.annotation.StringRes; import android.annotation.XmlRes; import android.content.pm.ActivityInfo; -import android.content.res.ColorStateList.ColorStateListFactory; import android.graphics.Movie; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; @@ -112,8 +111,8 @@ public class Resources { private static final LongSparseArray[] sPreloadedDrawables; private static final LongSparseArray sPreloadedColorDrawables = new LongSparseArray<>(); - private static final LongSparseArray sPreloadedColorStateLists - = new LongSparseArray<>(); + private static final LongSparseArray> + sPreloadedColorStateLists = new LongSparseArray<>(); // Pool of TypedArrays targeted to this Resources object. final SynchronizedPool mTypedArrayPool = new SynchronizedPool<>(5); @@ -2667,7 +2666,8 @@ public class Resources { // Handle inline color definitions. if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT && value.type <= TypedValue.TYPE_LAST_COLOR_INT) { - final ColorStateListFactory factory = sPreloadedColorStateLists.get(key); + final android.content.res.ConstantState factory = + sPreloadedColorStateLists.get(key); if (factory != null) { return factory.newInstance(); } @@ -2677,7 +2677,7 @@ public class Resources { if (mPreloading) { if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId, "color")) { - sPreloadedColorStateLists.put(key, csl.getFactory()); + sPreloadedColorStateLists.put(key, csl.getConstantState()); } } @@ -2691,7 +2691,8 @@ public class Resources { return csl; } - final ColorStateListFactory factory = sPreloadedColorStateLists.get(key); + final android.content.res.ConstantState factory = + sPreloadedColorStateLists.get(key); if (factory != null) { csl = factory.newInstance(this, theme); } @@ -2704,10 +2705,10 @@ public class Resources { if (mPreloading) { if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId, "color")) { - sPreloadedColorStateLists.put(key, csl.getFactory()); + sPreloadedColorStateLists.put(key, csl.getConstantState()); } } else { - cache.put(key, theme, csl.getFactory()); + cache.put(key, theme, csl.getConstantState()); } } diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index a56e87ef9efdb..28c26ff386830 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -173,7 +173,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { @Override public int getChangingConfigurations() { - return super.getChangingConfigurations() | mAnimatedVectorState.mChangingConfigurations; + return super.getChangingConfigurations() | mAnimatedVectorState.getChangingConfigurations(); } @Override diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java index dc10a813caa3b..6fe6b561c629c 100644 --- a/graphics/java/android/graphics/drawable/BitmapDrawable.java +++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java @@ -454,7 +454,7 @@ public class BitmapDrawable extends Drawable { @Override public int getChangingConfigurations() { - return super.getChangingConfigurations() | mBitmapState.mChangingConfigurations; + return super.getChangingConfigurations() | mBitmapState.getChangingConfigurations(); } private boolean needMirroring() { @@ -834,7 +834,7 @@ public class BitmapDrawable extends Drawable { // Apply theme to contained color state list. if (state.mTint != null && state.mTint.canApplyTheme()) { - state.mTint.applyTheme(t); + state.mTint = state.mTint.obtainForTheme(t); } // Update local properties. @@ -882,7 +882,7 @@ public class BitmapDrawable extends Drawable { @Override public final ConstantState getConstantState() { - mBitmapState.mChangingConfigurations = getChangingConfigurations(); + mBitmapState.mChangingConfigurations |= getChangingConfigurations(); return mBitmapState; } @@ -950,7 +950,8 @@ public class BitmapDrawable extends Drawable { @Override public int getChangingConfigurations() { - return mChangingConfigurations; + return mChangingConfigurations + | (mTint != null ? mTint.getChangingConfigurations() : 0); } } diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java index f75ab36b0e997..8e9162149ed11 100644 --- a/graphics/java/android/graphics/drawable/ColorDrawable.java +++ b/graphics/java/android/graphics/drawable/ColorDrawable.java @@ -276,7 +276,7 @@ public class ColorDrawable extends Drawable { } if (state.mTint != null && state.mTint.canApplyTheme()) { - state.mTint.applyTheme(t); + state.mTint = state.mTint.obtainForTheme(t); } updateLocalState(t.getResources()); @@ -327,7 +327,8 @@ public class ColorDrawable extends Drawable { @Override public int getChangingConfigurations() { - return mChangingConfigurations; + return mChangingConfigurations + | (mTint != null ? mTint.getChangingConfigurations() : 0); } } diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index ddcb48b5e03d3..b03fe3a103288 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -87,8 +87,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { @Override public int getChangingConfigurations() { return super.getChangingConfigurations() - | mDrawableContainerState.mChangingConfigurations - | mDrawableContainerState.mChildrenChangingConfigurations; + | mDrawableContainerState.getChangingConfigurations(); } private boolean needsMirroring() { @@ -865,6 +864,9 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { for (int i = 0; i < N; i++) { if (drawables[i] != null && drawables[i].canApplyTheme()) { drawables[i].applyTheme(theme); + + // Update cached mask of child changing configurations. + mChildrenChangingConfigurations |= drawables[i].getChangingConfigurations(); } } } diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java index 1d6c60f94b783..0da4275faba71 100644 --- a/graphics/java/android/graphics/drawable/DrawableWrapper.java +++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java @@ -180,8 +180,7 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb @Override public int getChangingConfigurations() { return super.getChangingConfigurations() - | (mState != null ? mState.mChangingConfigurations : 0) - | mDrawable.getChangingConfigurations(); + | (mState != null ? mState.getChangingConfigurations() : 0); } @Override @@ -433,7 +432,7 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb @Override public int getChangingConfigurations() { - return mChangingConfigurations; + return mChangingConfigurations | mDrawableState.getChangingConfigurations(); } public boolean canConstantState() { diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index eff152c8d2f48..4c2817c4459e4 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -491,19 +491,21 @@ public class GradientDrawable extends Drawable { } /** - *

Sets the colors used to draw the gradient. Each color is specified as an - * ARGB integer and the array must contain at least 2 colors.

- *

Note: changing colors will affect all instances - * of a drawable loaded from a resource. It is recommended to invoke - * {@link #mutate()} before changing the colors.

- * - * @param colors 2 or more ARGB colors + * Sets the colors used to draw the gradient. + *

+ * Each color is specified as an ARGB integer and the array must contain at + * least 2 colors. + *

+ * Note: changing colors will affect all instances of a + * drawable loaded from a resource. It is recommended to invoke + * {@link #mutate()} before changing the colors. * + * @param colors an array containing 2 or more ARGB colors * @see #mutate() * @see #setColor(int) */ public void setColors(@ColorInt int[] colors) { - mGradientState.setColors(colors); + mGradientState.setGradientColors(colors); mGradientIsDirty = true; invalidateSelf(); } @@ -568,7 +570,7 @@ public class GradientDrawable extends Drawable { mFillPaint.setAlpha(currFillAlpha); mFillPaint.setDither(st.mDither); mFillPaint.setColorFilter(colorFilter); - if (colorFilter != null && st.mColorStateList == null) { + if (colorFilter != null && st.mSolidColors == null) { mFillPaint.setColor(mAlpha << 24); } if (haveStroke) { @@ -715,7 +717,7 @@ public class GradientDrawable extends Drawable { * @see #setColors(int[]) */ public void setColor(@ColorInt int argb) { - mGradientState.setColorStateList(ColorStateList.valueOf(argb)); + mGradientState.setSolidColors(ColorStateList.valueOf(argb)); mFillPaint.setColor(argb); invalidateSelf(); } @@ -734,7 +736,7 @@ public class GradientDrawable extends Drawable { * @see #mutate() */ public void setColor(ColorStateList colorStateList) { - mGradientState.setColorStateList(colorStateList); + mGradientState.setSolidColors(colorStateList); final int color; if (colorStateList == null) { color = Color.TRANSPARENT; @@ -751,9 +753,9 @@ public class GradientDrawable extends Drawable { boolean invalidateSelf = false; final GradientState s = mGradientState; - final ColorStateList stateList = s.mColorStateList; - if (stateList != null) { - final int newColor = stateList.getColorForState(stateSet, 0); + final ColorStateList solidColors = s.mSolidColors; + if (solidColors != null) { + final int newColor = solidColors.getColorForState(stateSet, 0); final int oldColor = mFillPaint.getColor(); if (oldColor != newColor) { mFillPaint.setColor(newColor); @@ -763,12 +765,12 @@ public class GradientDrawable extends Drawable { final Paint strokePaint = mStrokePaint; if (strokePaint != null) { - final ColorStateList strokeStateList = s.mStrokeColorStateList; - if (strokeStateList != null) { - final int newStrokeColor = strokeStateList.getColorForState(stateSet, 0); - final int oldStrokeColor = strokePaint.getColor(); - if (oldStrokeColor != newStrokeColor) { - strokePaint.setColor(newStrokeColor); + final ColorStateList strokeColors = s.mStrokeColors; + if (strokeColors != null) { + final int newColor = strokeColors.getColorForState(stateSet, 0); + final int oldColor = strokePaint.getColor(); + if (oldColor != newColor) { + strokePaint.setColor(newColor); invalidateSelf = true; } } @@ -791,14 +793,14 @@ public class GradientDrawable extends Drawable { public boolean isStateful() { final GradientState s = mGradientState; return super.isStateful() - || (s.mColorStateList != null && s.mColorStateList.isStateful()) - || (s.mStrokeColorStateList != null && s.mStrokeColorStateList.isStateful()) + || (s.mSolidColors != null && s.mSolidColors.isStateful()) + || (s.mStrokeColors != null && s.mStrokeColors.isStateful()) || (s.mTint != null && s.mTint.isStateful()); } @Override public int getChangingConfigurations() { - return super.getChangingConfigurations() | mGradientState.mChangingConfigurations; + return super.getChangingConfigurations() | mGradientState.getChangingConfigurations(); } @Override @@ -899,10 +901,10 @@ public class GradientDrawable extends Drawable { mRect.set(bounds.left + inset, bounds.top + inset, bounds.right - inset, bounds.bottom - inset); - final int[] colors = st.mColors; - if (colors != null) { - RectF r = mRect; - float x0, x1, y0, y1; + final int[] gradientColors = st.mGradientColors; + if (gradientColors != null) { + final RectF r = mRect; + final float x0, x1, y0, y1; if (st.mGradient == LINEAR_GRADIENT) { final float level = st.mUseLevel ? getLevel() / 10000.0f : 1.0f; @@ -942,7 +944,7 @@ public class GradientDrawable extends Drawable { } mFillPaint.setShader(new LinearGradient(x0, y0, x1, y1, - colors, st.mPositions, Shader.TileMode.CLAMP)); + gradientColors, st.mPositions, Shader.TileMode.CLAMP)); } else if (st.mGradient == RADIAL_GRADIENT) { x0 = r.left + (r.right - r.left) * st.mCenterX; y0 = r.top + (r.bottom - r.top) * st.mCenterY; @@ -971,22 +973,22 @@ public class GradientDrawable extends Drawable { } mFillPaint.setShader(new RadialGradient( - x0, y0, radius, colors, null, Shader.TileMode.CLAMP)); + x0, y0, radius, gradientColors, null, Shader.TileMode.CLAMP)); } else if (st.mGradient == SWEEP_GRADIENT) { x0 = r.left + (r.right - r.left) * st.mCenterX; y0 = r.top + (r.bottom - r.top) * st.mCenterY; - int[] tempColors = colors; + int[] tempColors = gradientColors; float[] tempPositions = null; if (st.mUseLevel) { tempColors = st.mTempColors; - final int length = colors.length; + final int length = gradientColors.length; if (tempColors == null || tempColors.length != length + 1) { tempColors = st.mTempColors = new int[length + 1]; } - System.arraycopy(colors, 0, tempColors, 0, length); - tempColors[length] = colors[length - 1]; + System.arraycopy(gradientColors, 0, tempColors, 0, length); + tempColors[length] = gradientColors[length - 1]; tempPositions = st.mTempPositions; final float fraction = 1.0f / (length - 1); @@ -1006,7 +1008,7 @@ public class GradientDrawable extends Drawable { // If we don't have a solid color, the alpha channel must be // maxed out so that alpha modulation works correctly. - if (st.mColorStateList == null) { + if (st.mSolidColors == null) { mFillPaint.setColor(Color.BLACK); } } @@ -1044,15 +1046,15 @@ public class GradientDrawable extends Drawable { } if (state.mTint != null && state.mTint.canApplyTheme()) { - state.mTint.applyTheme(t); + state.mTint = state.mTint.obtainForTheme(t); } - if (state.mColorStateList != null && state.mColorStateList.canApplyTheme()) { - state.mColorStateList.applyTheme(t); + if (state.mSolidColors != null && state.mSolidColors.canApplyTheme()) { + state.mSolidColors = state.mSolidColors.obtainForTheme(t); } - if (state.mStrokeColorStateList != null && state.mStrokeColorStateList.canApplyTheme()) { - state.mStrokeColorStateList.applyTheme(t); + if (state.mStrokeColors != null && state.mStrokeColors.canApplyTheme()) { + state.mStrokeColors = state.mStrokeColors.obtainForTheme(t); } applyThemeChildElements(t); @@ -1288,7 +1290,7 @@ public class GradientDrawable extends Drawable { ColorStateList colorStateList = a.getColorStateList( R.styleable.GradientDrawableStroke_color); if (colorStateList == null) { - colorStateList = st.mStrokeColorStateList; + colorStateList = st.mStrokeColors; } if (dashWidth != 0.0f) { @@ -1346,10 +1348,10 @@ public class GradientDrawable extends Drawable { R.styleable.GradientDrawableGradient_endColor, 0); if (hasCenterColor) { - st.mColors = new int[3]; - st.mColors[0] = startColor; - st.mColors[1] = centerColor; - st.mColors[2] = endColor; + st.mGradientColors = new int[3]; + st.mGradientColors[0] = startColor; + st.mGradientColors[1] = centerColor; + st.mGradientColors[2] = endColor; st.mPositions = new float[3]; st.mPositions[0] = 0.0f; @@ -1357,9 +1359,9 @@ public class GradientDrawable extends Drawable { st.mPositions[1] = st.mCenterX != 0.5f ? st.mCenterX : st.mCenterY; st.mPositions[2] = 1f; } else { - st.mColors = new int[2]; - st.mColors[0] = startColor; - st.mColors[1] = endColor; + st.mGradientColors = new int[2]; + st.mGradientColors[0] = startColor; + st.mGradientColors[1] = endColor; } if (st.mGradient == LINEAR_GRADIENT) { @@ -1552,9 +1554,9 @@ public class GradientDrawable extends Drawable { public int mGradient = LINEAR_GRADIENT; public int mAngle = 0; public Orientation mOrientation; - public ColorStateList mColorStateList; - public ColorStateList mStrokeColorStateList; - public int[] mColors; + public ColorStateList mSolidColors; + public ColorStateList mStrokeColors; + public int[] mGradientColors; public int[] mTempColors; // no need to copy public float[] mTempPositions; // no need to copy public float[] mPositions; @@ -1593,9 +1595,9 @@ public class GradientDrawable extends Drawable { int[] mAttrCorners; int[] mAttrPadding; - public GradientState(Orientation orientation, int[] colors) { + public GradientState(Orientation orientation, int[] gradientColors) { mOrientation = orientation; - setColors(colors); + setGradientColors(gradientColors); } public GradientState(GradientState state) { @@ -1604,14 +1606,14 @@ public class GradientDrawable extends Drawable { mGradient = state.mGradient; mAngle = state.mAngle; mOrientation = state.mOrientation; - mColorStateList = state.mColorStateList; - if (state.mColors != null) { - mColors = state.mColors.clone(); + mSolidColors = state.mSolidColors; + if (state.mGradientColors != null) { + mGradientColors = state.mGradientColors.clone(); } if (state.mPositions != null) { mPositions = state.mPositions.clone(); } - mStrokeColorStateList = state.mStrokeColorStateList; + mStrokeColors = state.mStrokeColors; mStrokeWidth = state.mStrokeWidth; mStrokeDashWidth = state.mStrokeDashWidth; mStrokeDashGap = state.mStrokeDashGap; @@ -1655,8 +1657,8 @@ public class GradientDrawable extends Drawable { || mAttrSolid != null || mAttrStroke != null || mAttrCorners != null || mAttrPadding != null || (mTint != null && mTint.canApplyTheme()) - || (mStrokeColorStateList != null && mStrokeColorStateList.canApplyTheme()) - || (mColorStateList != null && mColorStateList.canApplyTheme()) + || (mStrokeColors != null && mStrokeColors.canApplyTheme()) + || (mSolidColors != null && mSolidColors.canApplyTheme()) || super.canApplyTheme(); } @@ -1672,7 +1674,10 @@ public class GradientDrawable extends Drawable { @Override public int getChangingConfigurations() { - return mChangingConfigurations; + return mChangingConfigurations + | (mStrokeColors != null ? mStrokeColors.getChangingConfigurations() : 0) + | (mSolidColors != null ? mSolidColors.getChangingConfigurations() : 0) + | (mTint != null ? mTint.getChangingConfigurations() : 0); } public void setShape(int shape) { @@ -1689,15 +1694,15 @@ public class GradientDrawable extends Drawable { mCenterY = y; } - public void setColors(int[] colors) { - mColors = colors; - mColorStateList = null; + public void setGradientColors(int[] colors) { + mGradientColors = colors; + mSolidColors = null; computeOpacity(); } - public void setColorStateList(ColorStateList colorStateList) { - mColors = null; - mColorStateList = colorStateList; + public void setSolidColors(ColorStateList colors) { + mGradientColors = null; + mSolidColors = colors; computeOpacity(); } @@ -1705,16 +1710,16 @@ public class GradientDrawable extends Drawable { mOpaqueOverBounds = false; mOpaqueOverShape = false; - if (mColors != null) { - for (int i = 0; i < mColors.length; i++) { - if (!isOpaque(mColors[i])) { + if (mGradientColors != null) { + for (int i = 0; i < mGradientColors.length; i++) { + if (!isOpaque(mGradientColors[i])) { return; } } } // An unfilled shape is not opaque over bounds or shape - if (mColors == null && mColorStateList == null) { + if (mGradientColors == null && mSolidColors == null) { return; } @@ -1726,10 +1731,9 @@ public class GradientDrawable extends Drawable { && mRadiusArray == null; } - public void setStroke( - int width, ColorStateList colorStateList, float dashWidth, float dashGap) { + public void setStroke(int width, ColorStateList colors, float dashWidth, float dashGap) { mStrokeWidth = width; - mStrokeColorStateList = colorStateList; + mStrokeColors = colors; mStrokeDashWidth = dashWidth; mStrokeDashGap = dashGap; computeOpacity(); @@ -1781,11 +1785,11 @@ public class GradientDrawable extends Drawable { private void updateLocalState(Resources res) { final GradientState state = mGradientState; - if (state.mColorStateList != null) { + if (state.mSolidColors != null) { final int[] currentState = getState(); - final int stateColor = state.mColorStateList.getColorForState(currentState, 0); + final int stateColor = state.mSolidColors.getColorForState(currentState, 0); mFillPaint.setColor(stateColor); - } else if (state.mColors == null) { + } else if (state.mGradientColors == null) { // If we don't have a solid color and we don't have a gradient, // the app is stroking the shape, set the color to the default // value of state.mSolidColor @@ -1802,9 +1806,9 @@ public class GradientDrawable extends Drawable { mStrokePaint.setStyle(Paint.Style.STROKE); mStrokePaint.setStrokeWidth(state.mStrokeWidth); - if (state.mStrokeColorStateList != null) { + if (state.mStrokeColors != null) { final int[] currentState = getState(); - final int strokeStateColor = state.mStrokeColorStateList.getColorForState( + final int strokeStateColor = state.mStrokeColors.getColorForState( currentState, 0); mStrokePaint.setColor(strokeStateColor); } diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java index 97f7105c4a024..e1ebdbb65a266 100644 --- a/graphics/java/android/graphics/drawable/InsetDrawable.java +++ b/graphics/java/android/graphics/drawable/InsetDrawable.java @@ -241,15 +241,6 @@ public class InsetDrawable extends DrawableWrapper { getDrawable().getOutline(outline); } - @Override - public ConstantState getConstantState() { - if (mState.canConstantState()) { - mState.mChangingConfigurations = getChangingConfigurations(); - return mState; - } - return null; - } - @Override DrawableWrapperState mutateConstantState() { mState = new InsetState(mState); @@ -257,11 +248,6 @@ public class InsetDrawable extends DrawableWrapper { } static final class InsetState extends DrawableWrapper.DrawableWrapperState { - int[] mThemeAttrs; - int mChangingConfigurations; - - ConstantState mDrawableState; - int mInsetLeft = 0; int mInsetTop = 0; int mInsetRight = 0; diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index 30fbe16a6dbdd..a2f71e5e30f2b 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -296,6 +296,9 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { final Drawable d = layer.mDrawable; if (d.canApplyTheme()) { d.applyTheme(t); + + // Update cached mask of child changing configurations. + state.mChildrenChangingConfigurations |= d.getChangingConfigurations(); } } @@ -882,9 +885,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { @Override public int getChangingConfigurations() { - return super.getChangingConfigurations() - | mLayerState.mChangingConfigurations - | mLayerState.mChildrenChangingConfigurations; + return super.getChangingConfigurations() | mLayerState.getChangingConfigurations(); } @Override @@ -1493,7 +1494,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { @Override public int getChangingConfigurations() { - return mChangingConfigurations; + return mChangingConfigurations + | mChildrenChangingConfigurations; } public final int getOpacity() { diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java index 487162e196393..9bf33cf244115 100644 --- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java +++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java @@ -266,7 +266,7 @@ public class NinePatchDrawable extends Drawable { @Override public int getChangingConfigurations() { - return super.getChangingConfigurations() | mNinePatchState.mChangingConfigurations; + return super.getChangingConfigurations() | mNinePatchState.getChangingConfigurations(); } @Override @@ -498,7 +498,7 @@ public class NinePatchDrawable extends Drawable { } if (state.mTint != null && state.mTint.canApplyTheme()) { - state.mTint.applyTheme(t); + state.mTint = state.mTint.obtainForTheme(t); } updateLocalState(t.getResources()); @@ -680,7 +680,8 @@ public class NinePatchDrawable extends Drawable { @Override public int getChangingConfigurations() { - return mChangingConfigurations; + return mChangingConfigurations + | (mTint != null ? mTint.getChangingConfigurations() : 0); } } diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java index 23f93fd3d78e4..6731a17492866 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -479,7 +479,7 @@ public class RippleDrawable extends LayerDrawable { } if (state.mColor != null && state.mColor.canApplyTheme()) { - state.mColor.applyTheme(t); + state.mColor = state.mColor.obtainForTheme(t); } updateLocalState(); @@ -955,6 +955,12 @@ public class RippleDrawable extends LayerDrawable { public Drawable newDrawable(Resources res) { return new RippleDrawable(this, res); } + + @Override + public int getChangingConfigurations() { + return super.getChangingConfigurations() + | (mColor != null ? mColor.getChangingConfigurations() : 0); + } } private RippleDrawable(RippleState state, Resources res) { diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java index 15e16f1e1233e..036a078eb00d5 100644 --- a/graphics/java/android/graphics/drawable/RotateDrawable.java +++ b/graphics/java/android/graphics/drawable/RotateDrawable.java @@ -89,9 +89,6 @@ public class RotateDrawable extends DrawableWrapper { final RotateState state = mState; - // Account for any configuration changes. - state.mChangingConfigurations |= a.getChangingConfigurations(); - // Extract the theme attributes, if any. state.mThemeAttrs = a.extractThemeAttrs(); diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java index fc88c15304824..532c51ce3954e 100644 --- a/graphics/java/android/graphics/drawable/ShapeDrawable.java +++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java @@ -261,8 +261,7 @@ public class ShapeDrawable extends Drawable { @Override public int getChangingConfigurations() { - return super.getChangingConfigurations() - | mShapeState.mChangingConfigurations; + return super.getChangingConfigurations() | mShapeState.getChangingConfigurations(); } /** @@ -427,7 +426,7 @@ public class ShapeDrawable extends Drawable { // Apply theme to contained color state list. if (state.mTint != null && state.mTint.canApplyTheme()) { - state.mTint.applyTheme(t); + state.mTint = state.mTint.obtainForTheme(t); } // Update local properties. @@ -578,7 +577,8 @@ public class ShapeDrawable extends Drawable { @Override public int getChangingConfigurations() { - return mChangingConfigurations; + return mChangingConfigurations + | (mTint != null ? mTint.getChangingConfigurations() : 0); } } diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index b82768255ca0f..a542feb51c748 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -389,7 +389,7 @@ public class VectorDrawable extends Drawable { // Apply theme to contained color state list. if (state.mTint != null && state.mTint.canApplyTheme()) { - state.mTint.applyTheme(t); + state.mTint = state.mTint.obtainForTheme(t); } final VPathRenderer path = state.mVPathRenderer; @@ -625,7 +625,7 @@ public class VectorDrawable extends Drawable { @Override public int getChangingConfigurations() { - return super.getChangingConfigurations() | mVectorState.mChangingConfigurations; + return super.getChangingConfigurations() | mVectorState.getChangingConfigurations(); } void setAllowCaching(boolean allowCaching) { @@ -784,7 +784,8 @@ public class VectorDrawable extends Drawable { @Override public int getChangingConfigurations() { - return mChangingConfigurations; + return mChangingConfigurations + | (mTint != null ? mTint.getChangingConfigurations() : 0); } }