Updated GradientDrawable to expose public APIs to
reduce reflection usages
--Marked GradientState parameter as hidden as each field on it is
accessible through GradientDrawable's public API
--Updated setColors API method to enable setting color stop positions
array
--Fixed issue where GradientDrawable with start/center/end colors
configured via xml would crash at runtime if the colors were modified
with a different number of colors. Resolved by providing optional
float array parameter that defaults to null if unset.
--Added public setters to GradientState parameters that were not
previously exposed
Bug: 124051827
Bug: 124051738
Bug: 124050218
Bug: 124050917
Test: Added CTS tests to GradientDrawableTest for new API coverage
Change-Id: I175998c9920d0ecca021fc3cac7d3a3f9e4b61cf
diff --git a/api/current.txt b/api/current.txt
index 673d90f..7b763ce 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -15409,28 +15409,38 @@
method public float getGradientCenterY();
method public float getGradientRadius();
method public int getGradientType();
+ method public int getInnerRadius();
+ method public float getInnerRadiusRatio();
method public int getOpacity();
method public android.graphics.drawable.GradientDrawable.Orientation getOrientation();
method public int getShape();
+ method public int getThickness();
+ method public float getThicknessRatio();
method public boolean getUseLevel();
method public void setAlpha(int);
method public void setColor(@ColorInt int);
method public void setColor(@Nullable android.content.res.ColorStateList);
method public void setColorFilter(@Nullable android.graphics.ColorFilter);
method public void setColors(@ColorInt int[]);
+ method public void setColors(@ColorInt int[], @Nullable float[]);
method public void setCornerRadii(@Nullable float[]);
method public void setCornerRadius(float);
method public void setDither(boolean);
method public void setGradientCenter(float, float);
method public void setGradientRadius(float);
method public void setGradientType(int);
+ method public void setInnerRadius(int);
+ method public void setInnerRadiusRatio(float);
method public void setOrientation(android.graphics.drawable.GradientDrawable.Orientation);
+ method public void setPadding(int, int, int, int);
method public void setShape(int);
method public void setSize(int, int);
method public void setStroke(int, @ColorInt int);
method public void setStroke(int, android.content.res.ColorStateList);
method public void setStroke(int, @ColorInt int, float, float);
method public void setStroke(int, android.content.res.ColorStateList, float, float);
+ method public void setThickness(int);
+ method public void setThicknessRatio(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/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 991847a..6ecb621 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -44,6 +44,7 @@
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.graphics.Xfermode;
+import android.os.Build;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -156,12 +157,12 @@
private static final float DEFAULT_INNER_RADIUS_RATIO = 3.0f;
private static final float DEFAULT_THICKNESS_RATIO = 9.0f;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
private GradientState mGradientState;
@UnsupportedAppUsage
private final Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124051827)
private Rect mPadding;
@UnsupportedAppUsage
private Paint mStrokePaint; // optional, set by the caller
@@ -670,7 +671,28 @@
* @see #setColor(int)
*/
public void setColors(@ColorInt int[] colors) {
+ setColors(colors, null);
+ }
+
+ /**
+ * Sets the colors and offsets used to draw the gradient.
+ * <p>
+ * Each color is specified as an ARGB integer and the array must contain at
+ * least 2 colors.
+ * <p>
+ * <strong>Note</strong>: 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
+ * @param offsets optional array of floating point parameters representing the positions
+ * of the colors. Null evenly disperses the colors
+ * @see #mutate()
+ * @see #setColors(int[])
+ */
+ public void setColors(@ColorInt int[] colors, @Nullable float[] offsets) {
mGradientState.setGradientColors(colors);
+ mGradientState.mPositions = offsets;
mGradientIsDirty = true;
invalidateSelf();
}
@@ -849,6 +871,115 @@
}
}
+ /**
+ * Inner radius of the ring expressed as a ratio of the ring's width.
+ *
+ * @see #getInnerRadiusRatio()
+ * @attr ref android.R.styleable#GradientDrawable_innerRadiusRatio
+ */
+ public void setInnerRadiusRatio(float innerRadiusRatio) {
+ mGradientState.mInnerRadiusRatio = innerRadiusRatio;
+ mPathIsDirty = true;
+ invalidateSelf();
+ }
+
+ /**
+ * Return the inner radius of the ring expressed as a ratio of the ring's width.
+ *
+ * @see #setInnerRadiusRatio(float)
+ * @attr ref android.R.styleable#GradientDrawable_innerRadiusRatio
+ */
+ public float getInnerRadiusRatio() {
+ return mGradientState.mInnerRadiusRatio;
+ }
+
+ /**
+ * Configure the inner radius of the ring.
+ *
+ * @see #getInnerRadius()
+ * @attr ref android.R.styleable#GradientDrawable_innerRadius
+ */
+ public void setInnerRadius(int innerRadius) {
+ mGradientState.mInnerRadius = innerRadius;
+ mPathIsDirty = true;
+ invalidateSelf();
+ }
+
+ /**
+ * Retrn the inner radius of the ring
+ *
+ * @see #setInnerRadius(int)
+ * @attr ref android.R.styleable#GradientDrawable_innerRadius
+ */
+ public int getInnerRadius() {
+ return mGradientState.mInnerRadius;
+ }
+
+ /**
+ * Configure the thickness of the ring expressed as a ratio of the ring's width.
+ *
+ * @see #getThicknessRatio()
+ * @attr ref android.R.styleable#GradientDrawable_thicknessRatio
+ */
+ public void setThicknessRatio(float thicknessRatio) {
+ mGradientState.mThicknessRatio = thicknessRatio;
+ mPathIsDirty = true;
+ invalidateSelf();
+ }
+
+ /**
+ * Return the thickness ratio of the ring expressed as a ratio of the ring's width.
+ *
+ * @see #setThicknessRatio(float)
+ * @attr ref android.R.styleable#GradientDrawable_thicknessRatio
+ */
+ public float getThicknessRatio() {
+ return mGradientState.mThicknessRatio;
+ }
+
+ /**
+ * Configure the thickness of the ring.
+ *
+ * @attr ref android.R.styleable#GradientDrawable_thickness
+ */
+ public void setThickness(int thickness) {
+ mGradientState.mThickness = thickness;
+ mPathIsDirty = true;
+ invalidateSelf();
+ }
+
+ /**
+ * Return the thickness of the ring
+ *
+ * @see #setThickness(int)
+ * @attr ref android.R.styleable#GradientDrawable_thickness
+ */
+ public int getThickness() {
+ return mGradientState.mThickness;
+ }
+
+ /**
+ * Configure the padding of the gradient shape
+ * @param left Left padding of the gradient shape
+ * @param top Top padding of the gradient shape
+ * @param right Right padding of the gradient shape
+ * @param bottom Bottom padding of the gradient shape
+ *
+ * @attr ref android.R.styleable#GradientDrawablePadding_left
+ * @attr ref android.R.styleable#GradientDrawablePadding_top
+ * @attr ref android.R.styleable#GradientDrawablePadding_right
+ * @attr ref android.R.styleable#GradientDrawablePadding_bottom
+ */
+ public void setPadding(int left, int top, int right, int bottom) {
+ if (mGradientState.mPadding == null) {
+ mGradientState.mPadding = new Rect();
+ }
+
+ mGradientState.mPadding.set(left, top, right, bottom);
+ mPadding = mGradientState.mPadding;
+ invalidateSelf();
+ }
+
private Path buildRing(GradientState st) {
if (mRingPath != null && (!st.mUseLevelForShape || !mPathIsDirty)) return mRingPath;
mPathIsDirty = false;
@@ -1814,46 +1945,46 @@
final static class GradientState extends ConstantState {
public @Config int mChangingConfigurations;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public @Shape int mShape = RECTANGLE;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public @GradientType int mGradient = LINEAR_GRADIENT;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public int mAngle = 0;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public Orientation mOrientation;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public ColorStateList mSolidColors;
public ColorStateList mStrokeColors;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public @ColorInt int[] mGradientColors;
public @ColorInt int[] mTempColors; // no need to copy
public float[] mTempPositions; // no need to copy
@UnsupportedAppUsage
public float[] mPositions;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public int mStrokeWidth = -1; // if >= 0 use stroking.
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public float mStrokeDashWidth = 0.0f;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public float mStrokeDashGap = 0.0f;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public float mRadius = 0.0f; // use this if mRadiusArray is null
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public float[] mRadiusArray = null;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public Rect mPadding = null;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public int mWidth = -1;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public int mHeight = -1;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public float mInnerRadiusRatio = DEFAULT_INNER_RADIUS_RATIO;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050218)
public float mThicknessRatio = DEFAULT_THICKNESS_RATIO;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public int mInnerRadius = -1;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050218)
public int mThickness = -1;
public boolean mDither = false;
public Insets mOpticalInsets = Insets.NONE;