Merge "Add support for using ColorStateList as GradientDrawable's stroke"
diff --git a/api/current.txt b/api/current.txt
index 3950924..9f80ef6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7634,11 +7634,9 @@
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 isOpaque();
method public boolean isStateful();
method public static android.content.res.ColorStateList valueOf(int);
method public android.content.res.ColorStateList withAlpha(int);
@@ -10284,6 +10282,7 @@
method public void draw(android.graphics.Canvas);
method public int getOpacity();
method public android.graphics.drawable.GradientDrawable.Orientation getOrientation();
+ method public boolean onStateChange(int[]);
method public void setAlpha(int);
method public void setColor(int);
method public void setColor(android.content.res.ColorStateList);
@@ -10298,7 +10297,9 @@
method public void setShape(int);
method public void setSize(int, int);
method public void setStroke(int, int);
+ method public void setStroke(int, android.content.res.ColorStateList);
method public void setStroke(int, int, float, float);
+ method public void setStroke(int, android.content.res.ColorStateList, float, float);
method public void setUseLevel(boolean);
field public static final int LINE = 2; // 0x2
field public static final int LINEAR_GRADIENT = 0; // 0x0
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index fe9305e..431226a 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -16,6 +16,7 @@
package android.content.res;
+import android.graphics.Color;
import com.android.internal.util.ArrayUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -259,7 +260,17 @@
public boolean isStateful() {
return mStateSpecs.length > 1;
}
-
+
+ public boolean isOpaque() {
+ final int n = mColors.length;
+ for (int i = 0; i < n; i++) {
+ if (Color.alpha(mColors[i]) != 0xFF) {
+ return false;
+ }
+ }
+ return true;
+ }
+
/**
* Return the color associated with the given set of {@link android.view.View} states.
*
@@ -281,31 +292,6 @@
}
/**
- * @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}.
*
* @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 27618a5..e51dfbc 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -234,6 +234,23 @@
}
/**
+ * <p>Set the stroke width and color state list for the drawable. If width
+ * is zero, then no stroke is drawn.</p>
+ * <p><strong>Note</strong>: changing this property will affect all instances
+ * of a drawable loaded from a resource. It is recommended to invoke
+ * {@link #mutate()} before changing this property.</p>
+ *
+ * @param width The width in pixels of the stroke
+ * @param colorStateList The color state list of the stroke
+ *
+ * @see #mutate()
+ * @see #setStroke(int, ColorStateList, float, float)
+ */
+ public void setStroke(int width, ColorStateList colorStateList) {
+ setStroke(width, colorStateList, 0, 0);
+ }
+
+ /**
* <p>Set the stroke width and color for the drawable. If width is zero,
* then no stroke is drawn. This method can also be used to dash the stroke.</p>
* <p><strong>Note</strong>: changing this property will affect all instances
@@ -250,7 +267,35 @@
*/
public void setStroke(int width, int color, float dashWidth, float dashGap) {
mGradientState.setStroke(width, color, dashWidth, dashGap);
+ setStrokeInternal(width, color, dashWidth, dashGap);
+ }
+ /**
+ * <p>Set the stroke width and color state list for the drawable. If width
+ * is zero, then no stroke is drawn. This method can also be used to dash
+ * the stroke.</p>
+ * <p><strong>Note</strong>: changing this property will affect all instances
+ * of a drawable loaded from a resource. It is recommended to invoke
+ * {@link #mutate()} before changing this property.</p>
+ *
+ * @param width The width in pixels of the stroke
+ * @param colorStateList The color state list of the stroke
+ * @param dashWidth The length in pixels of the dashes, set to 0 to disable dashes
+ * @param dashGap The gap in pixels between dashes
+ *
+ * @see #mutate()
+ * @see #setStroke(int, ColorStateList)
+ */
+ public void setStroke(
+ int width, ColorStateList colorStateList, float dashWidth, float dashGap) {
+ mGradientState.setStroke(width, colorStateList, dashWidth, dashGap);
+
+ final int[] stateSet = getState();
+ final int color = colorStateList.getColorForState(stateSet, 0);
+ setStrokeInternal(width, color, dashWidth, dashGap);
+ }
+
+ private void setStrokeInternal(int width, int color, float dashWidth, float dashGap) {
if (mStrokePaint == null) {
mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mStrokePaint.setStyle(Paint.Style.STROKE);
@@ -647,24 +692,44 @@
}
@Override
- public boolean setState(int[] stateSet) {
- final ColorStateList stateList = mGradientState.mColorStateList;
+ public boolean onStateChange(int[] stateSet) {
+ boolean invalidateSelf = false;
+
+ final GradientState s = mGradientState;
+ final ColorStateList stateList = s.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;
+ invalidateSelf |= true;
}
}
- return super.setState(stateSet);
+ final ColorStateList strokeStateList = s.mStrokeColorStateList;
+ if (strokeStateList != null) {
+ final int newColor = stateList.getColorForState(stateSet, 0);
+ final int oldColor = mStrokePaint.getColor();
+ if (oldColor != newColor) {
+ mStrokePaint.setColor(newColor);
+ invalidateSelf |= true;
+ }
+ }
+
+ if (invalidateSelf) {
+ invalidateSelf();
+ return true;
+ }
+
+ return false;
}
@Override
public boolean isStateful() {
- return super.isStateful() || mGradientState.mColorStateList != null;
+ final GradientState s = mGradientState;
+ return super.isStateful()
+ || (s.mColorStateList != null && s.mColorStateList.isStateful())
+ || (s.mStrokeColorStateList != null && s.mStrokeColorStateList.isStateful());
}
@Override
@@ -1015,18 +1080,18 @@
} else if (name.equals("stroke")) {
a = r.obtainAttributes(attrs,
com.android.internal.R.styleable.GradientDrawableStroke);
- int width = a.getDimensionPixelSize(
+ final int width = a.getDimensionPixelSize(
com.android.internal.R.styleable.GradientDrawableStroke_width, 0);
- int color = a.getColor(
- com.android.internal.R.styleable.GradientDrawableStroke_color, 0);
- float dashWidth = a.getDimension(
+ final ColorStateList colorStateList = a.getColorStateList(
+ com.android.internal.R.styleable.GradientDrawableStroke_color);
+ final float dashWidth = a.getDimension(
com.android.internal.R.styleable.GradientDrawableStroke_dashWidth, 0);
if (dashWidth != 0.0f) {
- float dashGap = a.getDimension(
+ final float dashGap = a.getDimension(
com.android.internal.R.styleable.GradientDrawableStroke_dashGap, 0);
- setStroke(width, color, dashWidth, dashGap);
+ setStroke(width, colorStateList, dashWidth, dashGap);
} else {
- setStroke(width, color);
+ setStroke(width, colorStateList);
}
a.recycle();
} else if (name.equals("corners")) {
@@ -1119,6 +1184,7 @@
public int mGradient = LINEAR_GRADIENT;
public Orientation mOrientation;
public ColorStateList mColorStateList;
+ public ColorStateList mStrokeColorStateList;
public int[] mColors;
public int[] mTempColors; // no need to copy
public float[] mTempPositions; // no need to copy
@@ -1251,12 +1317,19 @@
return;
}
- if (mStrokeWidth > 0 && !isOpaque(mStrokeColor)) {
- mOpaque = false;
- return;
+ if (mStrokeWidth > 0) {
+ if (mStrokeColorStateList != null) {
+ if (!mStrokeColorStateList.isOpaque()) {
+ mOpaque = false;
+ return;
+ }
+ } else if (!isOpaque(mStrokeColor)) {
+ mOpaque = false;
+ return;
+ }
}
- if (mColorStateList != null && !isOpaque(mColorStateList)) {
+ if (mColorStateList != null && !mColorStateList.isOpaque()) {
mOpaque = false;
return;
}
@@ -1282,25 +1355,26 @@
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;
+ mStrokeColorStateList = null;
computeOpacity();
}
public void setStroke(int width, int color, float dashWidth, float dashGap) {
mStrokeWidth = width;
mStrokeColor = color;
+ mStrokeColorStateList = null;
+ mStrokeDashWidth = dashWidth;
+ mStrokeDashGap = dashGap;
+ computeOpacity();
+ }
+
+ public void setStroke(
+ int width, ColorStateList colorStateList, float dashWidth, float dashGap) {
+ mStrokeWidth = width;
+ mStrokeColorStateList = colorStateList;
mStrokeDashWidth = dashWidth;
mStrokeDashGap = dashGap;
computeOpacity();