diff --git a/api/current.txt b/api/current.txt index d1b9ae5fde60b..5737b5d081b10 100644 --- a/api/current.txt +++ b/api/current.txt @@ -7628,8 +7628,11 @@ package android.content.res { ctor public ColorStateList(int[][], int[]); method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public int describeContents(); + method public int getColorAt(int); method public int getColorForState(int[], int); + method public int getCount(); method public int getDefaultColor(); + method public int[] getStateSpecAt(int); method public boolean isStateful(); method public static android.content.res.ColorStateList valueOf(int); method public android.content.res.ColorStateList withAlpha(int); @@ -10277,6 +10280,7 @@ package android.graphics.drawable { method public android.graphics.drawable.GradientDrawable.Orientation getOrientation(); method public void setAlpha(int); method public void setColor(int); + method public void setColor(android.content.res.ColorStateList); method public void setColorFilter(android.graphics.ColorFilter); method public void setColors(int[]); method public void setCornerRadii(float[]); diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java index bd23db46a1ee9..fe9305edbf5aa 100644 --- a/core/java/android/content/res/ColorStateList.java +++ b/core/java/android/content/res/ColorStateList.java @@ -280,6 +280,31 @@ public class ColorStateList implements Parcelable { return defaultColor; } + /** + * @return the number of state spec to color mappings in the list + * @see #getColorAt(int) + * @see #getStateSpecAt(int) + */ + public int getCount() { + return mColors.length; + } + + /** + * @return the state spec at the specified index in the list + * @see #getCount() + */ + public int[] getStateSpecAt(int index) { + return mStateSpecs[index]; + } + + /** + * @return the color at the specified index in the list + * @see #getCount() + */ + public int getColorAt(int index) { + return mColors[index]; + } + /** * Return the default color in this {@link ColorStateList}. * diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index b340777c78eb2..27618a56a0b9a 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -16,6 +16,7 @@ package android.graphics.drawable; +import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; @@ -24,12 +25,12 @@ import android.graphics.ColorFilter; import android.graphics.DashPathEffect; import android.graphics.LinearGradient; import android.graphics.Paint; +import android.graphics.Path; import android.graphics.PixelFormat; +import android.graphics.RadialGradient; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Shader; -import android.graphics.Path; -import android.graphics.RadialGradient; import android.graphics.SweepGradient; import android.util.AttributeSet; import android.util.Log; @@ -479,7 +480,8 @@ public class GradientDrawable extends Drawable { mFillPaint.setAlpha(currFillAlpha); mFillPaint.setDither(mDither); mFillPaint.setColorFilter(mColorFilter); - if (mColorFilter != null && !mGradientState.mHasSolidColor) { + if (mColorFilter != null && !mGradientState.mHasSolidColor + && mGradientState.mColorStateList == null) { mFillPaint.setColor(mAlpha << 24); } if (haveStroke) { @@ -610,7 +612,7 @@ public class GradientDrawable extends Drawable { } /** - *
Changes this drawbale to use a single color instead of a gradient.
+ *Changes this drawable to use a single color instead of a gradient.
*Note: changing color will affect all instances * of a drawable loaded from a resource. It is recommended to invoke * {@link #mutate()} before changing the color.
@@ -626,6 +628,45 @@ public class GradientDrawable extends Drawable { invalidateSelf(); } + /** + * Changes this drawable to use a single color state list instead of a + * gradient. + *+ * Note: changing color will affect all instances of a + * drawable loaded from a resource. It is recommended to invoke + * {@link #mutate()} before changing the color.
+ * + * @param colorStateList The color state list used to fill the shape + * @see #mutate() + */ + public void setColor(ColorStateList colorStateList) { + final int color = colorStateList.getColorForState(getState(), 0); + mGradientState.setColorStateList(colorStateList); + mFillPaint.setColor(color); + invalidateSelf(); + } + + @Override + public boolean setState(int[] stateSet) { + final ColorStateList stateList = mGradientState.mColorStateList; + if (stateList != null) { + final int newColor = stateList.getColorForState(stateSet, 0); + final int oldColor = mFillPaint.getColor(); + if (oldColor != newColor) { + mFillPaint.setColor(newColor); + invalidateSelf(); + return true; + } + } + + return super.setState(stateSet); + } + + @Override + public boolean isStateful() { + return super.isStateful() || mGradientState.mColorStateList != null; + } + @Override public int getChangingConfigurations() { return super.getChangingConfigurations() | mGradientState.mChangingConfigurations; @@ -791,7 +832,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.mHasSolidColor) { + if (!st.mHasSolidColor && st.mColorStateList == null) { mFillPaint.setColor(Color.BLACK); } } @@ -967,10 +1008,10 @@ public class GradientDrawable extends Drawable { } else if (name.equals("solid")) { a = r.obtainAttributes(attrs, com.android.internal.R.styleable.GradientDrawableSolid); - int argb = a.getColor( - com.android.internal.R.styleable.GradientDrawableSolid_color, 0); + final ColorStateList colorStateList = a.getColorStateList( + com.android.internal.R.styleable.GradientDrawableSolid_color); a.recycle(); - setColor(argb); + setColor(colorStateList); } else if (name.equals("stroke")) { a = r.obtainAttributes(attrs, com.android.internal.R.styleable.GradientDrawableStroke); @@ -1077,6 +1118,7 @@ public class GradientDrawable extends Drawable { public int mShape = RECTANGLE; public int mGradient = LINEAR_GRADIENT; public Orientation mOrientation; + public ColorStateList mColorStateList; public int[] mColors; public int[] mTempColors; // no need to copy public float[] mTempPositions; // no need to copy @@ -1113,6 +1155,7 @@ public class GradientDrawable extends Drawable { mShape = state.mShape; mGradient = state.mGradient; mOrientation = state.mOrientation; + mColorStateList = state.mColorStateList; if (state.mColors != null) { mColors = state.mColors.clone(); } @@ -1178,6 +1221,7 @@ public class GradientDrawable extends Drawable { public void setColors(int[] colors) { mHasSolidColor = false; mColors = colors; + mColorStateList = null; computeOpacity(); } @@ -1185,6 +1229,14 @@ public class GradientDrawable extends Drawable { mHasSolidColor = true; mSolidColor = argb; mColors = null; + mColorStateList = null; + computeOpacity(); + } + + public void setColorStateList(ColorStateList colorStateList) { + mHasSolidColor = false; + mColors = null; + mColorStateList = colorStateList; computeOpacity(); } @@ -1203,7 +1255,12 @@ public class GradientDrawable extends Drawable { mOpaque = false; return; } - + + if (mColorStateList != null && !isOpaque(mColorStateList)) { + mOpaque = false; + return; + } + if (mHasSolidColor) { mOpaque = isOpaque(mSolidColor); return; @@ -1225,6 +1282,16 @@ public class GradientDrawable extends Drawable { return ((color >> 24) & 0xff) == 0xff; } + private static boolean isOpaque(ColorStateList colors) { + final int n = colors.getCount(); + for (int i = 0; i < n; i++) { + if (!isOpaque(colors.getColorAt(i))) { + return false; + } + } + return true; + } + public void setStroke(int width, int color) { mStrokeWidth = width; mStrokeColor = color; @@ -1274,6 +1341,10 @@ public class GradientDrawable extends Drawable { private void initializeWithState(GradientState state) { if (state.mHasSolidColor) { mFillPaint.setColor(state.mSolidColor); + } else if (state.mColorStateList != null) { + final int[] currentState = getState(); + final int stateColor = state.mColorStateList.getColorForState(currentState, 0); + mFillPaint.setColor(stateColor); } else if (state.mColors == 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