package com.gh.common.databind; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.InsetDrawable; import android.graphics.drawable.StateListDrawable; import android.view.View; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field; import androidx.annotation.ColorInt; import androidx.annotation.IntDef; import androidx.databinding.BindingAdapter; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.PARAMETER; public class DrawablesBindingAdapter { private static final String TAG = "Drawables"; private static final int INVALID = 0; private static final int[] TMP_PADDING = new int[4]; // normal, checked, checkable, enabled, focused, pressed, selected @BindingAdapter(value = { "drawable_shapeMode", "drawable_solidColor", "drawable_strokeColor", "drawable_strokeWidth", "drawable_strokeDash", "drawable_strokeDashGap", "drawable_radius", "drawable_radiusLT", "drawable_radiusLB", "drawable_radiusRT", "drawable_radiusRB", "drawable_startColor", "drawable_centerColor", "drawable_endColor", "drawable_orientation", "drawable_gradientType", "drawable_radialCenterX", "drawable_radialCenterY", "drawable_radialRadius", "drawable_width", "drawable_height", "drawable_marginLeft", "drawable_marginTop", "drawable_marginRight", "drawable_marginBottom", "drawable_ringThickness", "drawable_ringThicknessRatio", "drawable_ringInnerRadius", "drawable_ringInnerRadiusRatio", "drawable_checked_shapeMode", "drawable_checked_solidColor", "drawable_checked_strokeColor", "drawable_checked_strokeWidth", "drawable_checked_strokeDash", "drawable_checked_strokeDashGap", "drawable_checked_radius", "drawable_checked_radiusLT", "drawable_checked_radiusLB", "drawable_checked_radiusRT", "drawable_checked_radiusRB", "drawable_checked_startColor", "drawable_checked_centerColor", "drawable_checked_endColor", "drawable_checked_orientation", "drawable_checked_gradientType", "drawable_checked_radialCenterX", "drawable_checked_radialCenterY", "drawable_checked_radialRadius", "drawable_checked_width", "drawable_checked_height", "drawable_checked_marginLeft", "drawable_checked_marginTop", "drawable_checked_marginRight", "drawable_checked_marginBottom", "drawable_checked_ringThickness", "drawable_checked_ringThicknessRatio", "drawable_checked_ringInnerRadius", "drawable_checked_ringInnerRadiusRatio", "drawable_checkable_shapeMode", "drawable_checkable_solidColor", "drawable_checkable_strokeColor", "drawable_checkable_strokeWidth", "drawable_checkable_strokeDash", "drawable_checkable_strokeDashGap", "drawable_checkable_radius", "drawable_checkable_radiusLT", "drawable_checkable_radiusLB", "drawable_checkable_radiusRT", "drawable_checkable_radiusRB", "drawable_checkable_startColor", "drawable_checkable_centerColor", "drawable_checkable_endColor", "drawable_checkable_orientation", "drawable_checkable_gradientType", "drawable_checkable_radialCenterX", "drawable_checkable_radialCenterY", "drawable_checkable_radialRadius", "drawable_checkable_width", "drawable_checkable_height", "drawable_checkable_marginLeft", "drawable_checkable_marginTop", "drawable_checkable_marginRight", "drawable_checkable_marginBottom", "drawable_checkable_ringThickness", "drawable_checkable_ringThicknessRatio", "drawable_checkable_ringInnerRadius", "drawable_checkable_ringInnerRadiusRatio", "drawable_enabled_shapeMode", "drawable_enabled_solidColor", "drawable_enabled_strokeColor", "drawable_enabled_strokeWidth", "drawable_enabled_strokeDash", "drawable_enabled_strokeDashGap", "drawable_enabled_radius", "drawable_enabled_radiusLT", "drawable_enabled_radiusLB", "drawable_enabled_radiusRT", "drawable_enabled_radiusRB", "drawable_enabled_startColor", "drawable_enabled_centerColor", "drawable_enabled_endColor", "drawable_enabled_orientation", "drawable_enabled_gradientType", "drawable_enabled_radialCenterX", "drawable_enabled_radialCenterY", "drawable_enabled_radialRadius", "drawable_enabled_width", "drawable_enabled_height", "drawable_enabled_marginLeft", "drawable_enabled_marginTop", "drawable_enabled_marginRight", "drawable_enabled_marginBottom", "drawable_enabled_ringThickness", "drawable_enabled_ringThicknessRatio", "drawable_enabled_ringInnerRadius", "drawable_enabled_ringInnerRadiusRatio", "drawable_focused_shapeMode", "drawable_focused_solidColor", "drawable_focused_strokeColor", "drawable_focused_strokeWidth", "drawable_focused_strokeDash", "drawable_focused_strokeDashGap", "drawable_focused_radius", "drawable_focused_radiusLT", "drawable_focused_radiusLB", "drawable_focused_radiusRT", "drawable_focused_radiusRB", "drawable_focused_startColor", "drawable_focused_centerColor", "drawable_focused_endColor", "drawable_focused_orientation", "drawable_focused_gradientType", "drawable_focused_radialCenterX", "drawable_focused_radialCenterY", "drawable_focused_radialRadius", "drawable_focused_width", "drawable_focused_height", "drawable_focused_marginLeft", "drawable_focused_marginTop", "drawable_focused_marginRight", "drawable_focused_marginBottom", "drawable_focused_ringThickness", "drawable_focused_ringThicknessRatio", "drawable_focused_ringInnerRadius", "drawable_focused_ringInnerRadiusRatio", "drawable_pressed_shapeMode", "drawable_pressed_solidColor", "drawable_pressed_strokeColor", "drawable_pressed_strokeWidth", "drawable_pressed_strokeDash", "drawable_pressed_strokeDashGap", "drawable_pressed_radius", "drawable_pressed_radiusLT", "drawable_pressed_radiusLB", "drawable_pressed_radiusRT", "drawable_pressed_radiusRB", "drawable_pressed_startColor", "drawable_pressed_centerColor", "drawable_pressed_endColor", "drawable_pressed_orientation", "drawable_pressed_gradientType", "drawable_pressed_radialCenterX", "drawable_pressed_radialCenterY", "drawable_pressed_radialRadius", "drawable_pressed_width", "drawable_pressed_height", "drawable_pressed_marginLeft", "drawable_pressed_marginTop", "drawable_pressed_marginRight", "drawable_pressed_marginBottom", "drawable_pressed_ringThickness", "drawable_pressed_ringThicknessRatio", "drawable_pressed_ringInnerRadius", "drawable_pressed_ringInnerRadiusRatio", "drawable_selected_shapeMode", "drawable_selected_solidColor", "drawable_selected_strokeColor", "drawable_selected_strokeWidth", "drawable_selected_strokeDash", "drawable_selected_strokeDashGap", "drawable_selected_radius", "drawable_selected_radiusLT", "drawable_selected_radiusLB", "drawable_selected_radiusRT", "drawable_selected_radiusRB", "drawable_selected_startColor", "drawable_selected_centerColor", "drawable_selected_endColor", "drawable_selected_orientation", "drawable_selected_gradientType", "drawable_selected_radialCenterX", "drawable_selected_radialCenterY", "drawable_selected_radialRadius", "drawable_selected_width", "drawable_selected_height", "drawable_selected_marginLeft", "drawable_selected_marginTop", "drawable_selected_marginRight", "drawable_selected_marginBottom", "drawable_selected_ringThickness", "drawable_selected_ringThicknessRatio", "drawable_selected_ringInnerRadius", "drawable_selected_ringInnerRadiusRatio", // normal, checked, checkable, enabled, focused, pressed, selected "drawable", "drawable_checked", "drawable_checkable", "drawable_enabled", "drawable_focused", "drawable_pressed", "drawable_selected", }, requireAll = false) public static void setViewBackground( View view, @ShapeMode int shapeMode, @ColorInt Integer solidColor, @ColorInt int strokeColor, float strokeWidth, float strokeDash, float strokeDashGap, float radius, float radiusLT, float radiusLB, float radiusRT, float radiusRB, @ColorInt Integer startColor, @ColorInt Integer centerColor, @ColorInt Integer endColor, @Orientation int orientation, @GradientType int gradientType, Float radialCenterX, Float radialCenterY, float radialRadius, float width, float height, float marginLeft, float marginTop, float marginRight, float marginBottom, float ringThickness, float ringThicknessRatio, float ringInnerRadius, float ringInnerRadiusRatio, @ShapeMode int checked_shapeMode, @ColorInt Integer checked_solidColor, @ColorInt int checked_strokeColor, float checked_strokeWidth, float checked_strokeDash, float checked_strokeDashGap, float checked_radius, float checked_radiusLT, float checked_radiusLB, float checked_radiusRT, float checked_radiusRB, @ColorInt Integer checked_startColor, @ColorInt Integer checked_centerColor, @ColorInt Integer checked_endColor, @Orientation int checked_orientation, @GradientType int checked_gradientType, Float checked_radialCenterX, Float checked_radialCenterY, float checked_radialRadius, float checked_width, float checked_height, float checked_marginLeft, float checked_marginTop, float checked_marginRight, float checked_marginBottom, float checked_ringThickness, float checked_ringThicknessRatio, float checked_ringInnerRadius, float checked_ringInnerRadiusRatio, @ShapeMode int checkable_shapeMode, @ColorInt Integer checkable_solidColor, @ColorInt int checkable_strokeColor, float checkable_strokeWidth, float checkable_strokeDash, float checkable_strokeDashGap, float checkable_radius, float checkable_radiusLT, float checkable_radiusLB, float checkable_radiusRT, float checkable_radiusRB, @ColorInt Integer checkable_startColor, @ColorInt Integer checkable_centerColor, @ColorInt Integer checkable_endColor, @Orientation int checkable_orientation, @GradientType int checkable_gradientType, Float checkable_radialCenterX, Float checkable_radialCenterY, float checkable_radialRadius, float checkable_width, float checkable_height, float checkable_marginLeft, float checkable_marginTop, float checkable_marginRight, float checkable_marginBottom, float checkable_ringThickness, float checkable_ringThicknessRatio, float checkable_ringInnerRadius, float checkable_ringInnerRadiusRatio, @ShapeMode int enabled_shapeMode, @ColorInt Integer enabled_solidColor, @ColorInt int enabled_strokeColor, float enabled_strokeWidth, float enabled_strokeDash, float enabled_strokeDashGap, float enabled_radius, float enabled_radiusLT, float enabled_radiusLB, float enabled_radiusRT, float enabled_radiusRB, @ColorInt Integer enabled_startColor, @ColorInt Integer enabled_centerColor, @ColorInt Integer enabled_endColor, @Orientation int enabled_orientation, @GradientType int enabled_gradientType, Float enabled_radialCenterX, Float enabled_radialCenterY, float enabled_radialRadius, float enabled_width, float enabled_height, float enabled_marginLeft, float enabled_marginTop, float enabled_marginRight, float enabled_marginBottom, float enabled_ringThickness, float enabled_ringThicknessRatio, float enabled_ringInnerRadius, float enabled_ringInnerRadiusRatio, @ShapeMode int focused_shapeMode, @ColorInt Integer focused_solidColor, @ColorInt int focused_strokeColor, float focused_strokeWidth, float focused_strokeDash, float focused_strokeDashGap, float focused_radius, float focused_radiusLT, float focused_radiusLB, float focused_radiusRT, float focused_radiusRB, @ColorInt Integer focused_startColor, @ColorInt Integer focused_centerColor, @ColorInt Integer focused_endColor, @Orientation int focused_orientation, @GradientType int focused_gradientType, Float focused_radialCenterX, Float focused_radialCenterY, float focused_radialRadius, float focused_width, float focused_height, float focused_marginLeft, float focused_marginTop, float focused_marginRight, float focused_marginBottom, float focused_ringThickness, float focused_ringThicknessRatio, float focused_ringInnerRadius, float focused_ringInnerRadiusRatio, @ShapeMode int pressed_shapeMode, @ColorInt Integer pressed_solidColor, @ColorInt int pressed_strokeColor, float pressed_strokeWidth, float pressed_strokeDash, float pressed_strokeDashGap, float pressed_radius, float pressed_radiusLT, float pressed_radiusLB, float pressed_radiusRT, float pressed_radiusRB, @ColorInt Integer pressed_startColor, @ColorInt Integer pressed_centerColor, @ColorInt Integer pressed_endColor, @Orientation int pressed_orientation, @GradientType int pressed_gradientType, Float pressed_radialCenterX, Float pressed_radialCenterY, float pressed_radialRadius, float pressed_width, float pressed_height, float pressed_marginLeft, float pressed_marginTop, float pressed_marginRight, float pressed_marginBottom, float pressed_ringThickness, float pressed_ringThicknessRatio, float pressed_ringInnerRadius, float pressed_ringInnerRadiusRatio, @ShapeMode int selected_shapeMode, @ColorInt Integer selected_solidColor, @ColorInt int selected_strokeColor, float selected_strokeWidth, float selected_strokeDash, float selected_strokeDashGap, float selected_radius, float selected_radiusLT, float selected_radiusLB, float selected_radiusRT, float selected_radiusRB, @ColorInt Integer selected_startColor, @ColorInt Integer selected_centerColor, @ColorInt Integer selected_endColor, @Orientation int selected_orientation, @GradientType int selected_gradientType, Float selected_radialCenterX, Float selected_radialCenterY, float selected_radialRadius, float selected_width, float selected_height, float selected_marginLeft, float selected_marginTop, float selected_marginRight, float selected_marginBottom, float selected_ringThickness, float selected_ringThicknessRatio, float selected_ringInnerRadius, float selected_ringInnerRadiusRatio, Drawable drawable, Drawable drawable_checked, Drawable drawable_checkable, Drawable drawable_enabled, Drawable drawable_focused, Drawable drawable_pressed, Drawable drawable_selected ) { boolean isDefaultNull = false; int count = 0; Drawable defaultDrawable = drawable != null ? drawable : create( shapeMode, solidColor, strokeColor, strokeWidth, strokeDash, strokeDashGap, radius, radiusLT, radiusLB, radiusRT, radiusRB, startColor, centerColor, endColor, orientation, gradientType, radialCenterX, radialCenterY, radialRadius, width, height, marginLeft, marginTop, marginRight, marginBottom, ringThickness, ringThicknessRatio, ringInnerRadius, ringInnerRadiusRatio ); if (defaultDrawable != null) { count++; } else { isDefaultNull = true; } Drawable checkedDrawable = drawable_checked != null ? drawable_checked : create( checked_shapeMode, checked_solidColor, checked_strokeColor, checked_strokeWidth, checked_strokeDash, checked_strokeDashGap, checked_radius, checked_radiusLT, checked_radiusLB, checked_radiusRT, checked_radiusRB, checked_startColor, checked_centerColor, checked_endColor, checked_orientation, checked_gradientType, checked_radialCenterX, checked_radialCenterY, checked_radialRadius, checked_width, checked_height, checked_marginLeft, checked_marginTop, checked_marginRight, checked_marginBottom, checked_ringThickness, checked_ringThicknessRatio, checked_ringInnerRadius, checked_ringInnerRadiusRatio ); if (checkedDrawable != null) { count++; } Drawable checkableDrawable = drawable_checkable != null ? drawable_checkable : create( checkable_shapeMode, checkable_solidColor, checkable_strokeColor, checkable_strokeWidth, checkable_strokeDash, checkable_strokeDashGap, checkable_radius, checkable_radiusLT, checkable_radiusLB, checkable_radiusRT, checkable_radiusRB, checkable_startColor, checkable_centerColor, checkable_endColor, checkable_orientation, checkable_gradientType, checkable_radialCenterX, checkable_radialCenterY, checkable_radialRadius, checkable_width, checkable_height, checkable_marginLeft, checkable_marginTop, checkable_marginRight, checkable_marginBottom, checkable_ringThickness, checkable_ringThicknessRatio, checkable_ringInnerRadius, checkable_ringInnerRadiusRatio ); if (checkableDrawable != null) { count++; } Drawable enabledDrawable = drawable_enabled != null ? drawable_enabled : create( enabled_shapeMode, enabled_solidColor, enabled_strokeColor, enabled_strokeWidth, enabled_strokeDash, enabled_strokeDashGap, enabled_radius, enabled_radiusLT, enabled_radiusLB, enabled_radiusRT, enabled_radiusRB, enabled_startColor, enabled_centerColor, enabled_endColor, enabled_orientation, enabled_gradientType, enabled_radialCenterX, enabled_radialCenterY, enabled_radialRadius, enabled_width, enabled_height, enabled_marginLeft, enabled_marginTop, enabled_marginRight, enabled_marginBottom, enabled_ringThickness, enabled_ringThicknessRatio, enabled_ringInnerRadius, enabled_ringInnerRadiusRatio ); if (enabledDrawable != null) { count++; } Drawable focusedDrawable = drawable_focused != null ? drawable_focused : create( focused_shapeMode, focused_solidColor, focused_strokeColor, focused_strokeWidth, focused_strokeDash, focused_strokeDashGap, focused_radius, focused_radiusLT, focused_radiusLB, focused_radiusRT, focused_radiusRB, focused_startColor, focused_centerColor, focused_endColor, focused_orientation, focused_gradientType, focused_radialCenterX, focused_radialCenterY, focused_radialRadius, focused_width, focused_height, focused_marginLeft, focused_marginTop, focused_marginRight, focused_marginBottom, focused_ringThickness, focused_ringThicknessRatio, focused_ringInnerRadius, focused_ringInnerRadiusRatio ); if (focusedDrawable != null) { count++; } Drawable pressedDrawable = drawable_pressed != null ? drawable_pressed : create( pressed_shapeMode, pressed_solidColor, pressed_strokeColor, pressed_strokeWidth, pressed_strokeDash, pressed_strokeDashGap, pressed_radius, pressed_radiusLT, pressed_radiusLB, pressed_radiusRT, pressed_radiusRB, pressed_startColor, pressed_centerColor, pressed_endColor, pressed_orientation, pressed_gradientType, pressed_radialCenterX, pressed_radialCenterY, pressed_radialRadius, pressed_width, pressed_height, pressed_marginLeft, pressed_marginTop, pressed_marginRight, pressed_marginBottom, pressed_ringThickness, pressed_ringThicknessRatio, pressed_ringInnerRadius, pressed_ringInnerRadiusRatio ); if (pressedDrawable != null) { count++; } Drawable selectedDrawable = drawable_selected != null ? drawable_selected : create( selected_shapeMode, selected_solidColor, selected_strokeColor, selected_strokeWidth, selected_strokeDash, selected_strokeDashGap, selected_radius, selected_radiusLT, selected_radiusLB, selected_radiusRT, selected_radiusRB, selected_startColor, selected_centerColor, selected_endColor, selected_orientation, selected_gradientType, selected_radialCenterX, selected_radialCenterY, selected_radialRadius, selected_width, selected_height, selected_marginLeft, selected_marginTop, selected_marginRight, selected_marginBottom, selected_ringThickness, selected_ringThicknessRatio, selected_ringInnerRadius, selected_ringInnerRadiusRatio ); if (selectedDrawable != null) { count++; } //noinspection StatementWithEmptyBody if (count < 1) { // impossible,因为该方法被调用说明至少声明了一条属性 } else { boolean needReSetPadding = false; if (isDefaultNull || count == 1) { // 当设置了margin(非view的margin)时,InsetDrawable会导致view本身的padding失效 needReSetPadding = true; TMP_PADDING[0] = view.getPaddingLeft(); TMP_PADDING[1] = view.getPaddingTop(); TMP_PADDING[2] = view.getPaddingRight(); TMP_PADDING[3] = view.getPaddingBottom(); } if (count == 1 && !isDefaultNull) { view.setBackground(defaultDrawable); } else { ProxyDrawable listDrawable = new ProxyDrawable(); if (checkedDrawable != null) { listDrawable.addState(new int[]{android.R.attr.state_checked}, checkedDrawable); } if (checkableDrawable != null) { listDrawable.addState(new int[]{android.R.attr.state_checkable}, checkableDrawable); } if (enabledDrawable != null) { listDrawable.addState(new int[]{android.R.attr.state_enabled}, enabledDrawable); } if (focusedDrawable != null) { listDrawable.addState(new int[]{android.R.attr.state_focused}, focusedDrawable); } if (pressedDrawable != null) { listDrawable.addState(new int[]{android.R.attr.state_pressed}, pressedDrawable); } if (selectedDrawable != null) { listDrawable.addState(new int[]{android.R.attr.state_selected}, selectedDrawable); } if (defaultDrawable != null) { listDrawable.addState(new int[]{0}, defaultDrawable); } else { Drawable originDrawable = view.getBackground(); if (originDrawable != null) { if (originDrawable instanceof ProxyDrawable) { originDrawable = ((ProxyDrawable) originDrawable).getOriginDrawable(); } listDrawable.addState(new int[]{0}, originDrawable); } } view.setBackground(listDrawable); } if (needReSetPadding) { view.setPadding(TMP_PADDING[0], TMP_PADDING[1], TMP_PADDING[2], TMP_PADDING[3]); } } } public static Drawable create( @ShapeMode int shapeMode, @ColorInt Integer solidColor, @ColorInt int strokeColor, @DP float strokeWidth, @DP float strokeDash, @DP float strokeDashGap, @DP float radius, @DP float radiusLT, @DP float radiusLB, @DP float radiusRT, @DP float radiusRB, @ColorInt Integer startColor, @ColorInt Integer centerColor, @ColorInt Integer endColor, @Orientation int orientation, @GradientType int gradientType, Float radialCenterX, Float radialCenterY, float radialRadius, @DP float width, @DP float height, @DP float marginLeft, @DP float marginTop, @DP float marginRight, @DP float marginBottom, @DP float ringThickness, @DP float ringThicknessRatio, @DP float ringInnerRadius, @DP float ringInnerRadiusRatio ) { if (shapeMode == INVALID && solidColor == null && strokeColor == INVALID && strokeWidth == INVALID && strokeDash == INVALID && strokeDashGap == INVALID && radius == INVALID && radiusLT == INVALID && radiusLB == INVALID && radiusRT == INVALID && radiusRB == INVALID && startColor == null && centerColor == null && endColor == null && orientation == INVALID && gradientType == INVALID && radialCenterX == null && radialCenterY == null && radialRadius == INVALID && width == INVALID && height == INVALID && marginLeft == INVALID && marginTop == INVALID && marginRight == INVALID && marginBottom == INVALID ) { // 这里需要判断empty,因为有可能只设置了一个state的drawable,那么其他state的就是empty了 return null; } GradientDrawable drawable = new GradientDrawable(); if (startColor != null && endColor != null) { int[] colors; if (centerColor != null) { colors = new int[3]; colors[0] = startColor; colors[1] = centerColor; colors[2] = endColor; } else { colors = new int[2]; colors[0] = startColor; colors[1] = endColor; } drawable.setColors(colors); drawable.setOrientation(mapOrientation(orientation)); drawable.setGradientType(gradientType); if (gradientType == GradientType.RADIAL) { drawable.setGradientCenter(radialCenterX == null ? .5f : radialCenterX, radialCenterY == null ? .5f : radialCenterY); drawable.setGradientRadius(dip2px(radialRadius)); } } else { if (solidColor != null) { drawable.setColor(solidColor); } } drawable.setShape(validShapeMode(shapeMode)); if (shapeMode == ShapeMode.RING) { // 由于GradientDrawable中没有ring相关的公开API,所以使用反射,若对性能有要求,请注意。 setRingValue(drawable, ringThickness, ringThicknessRatio, ringInnerRadius, ringInnerRadiusRatio); } if (strokeWidth > 0) { drawable.setStroke(dip2px(strokeWidth), strokeColor, dip2px(strokeDash), dip2px(strokeDashGap)); } if (radius <= 0) { float[] radiusEach = new float[]{dip2px(radiusLT), dip2px(radiusLT), dip2px(radiusRT), dip2px(radiusRT), dip2px(radiusRB), dip2px(radiusRB), dip2px(radiusLB), dip2px(radiusLB)}; drawable.setCornerRadii(radiusEach); } else { drawable.setCornerRadius(dip2px(radius)); } if (width > 0 && height > 0) { // https://stackoverflow.com/a/29180660/4698946 drawable.setSize(dip2px(width), dip2px(height)); } if (marginLeft != 0 || marginTop != 0 || marginRight != 0 || marginBottom != 0) { return new InsetDrawable(drawable, dip2px(marginLeft), dip2px(marginTop), dip2px(marginRight), dip2px(marginBottom)); } else { return drawable; } } private static int validShapeMode(@ShapeMode int shapeMode) { return shapeMode > ShapeMode.RING || shapeMode < ShapeMode.RECTANGLE ? GradientDrawable.RECTANGLE : shapeMode; } private static GradientDrawable.Orientation mapOrientation(@Orientation int orientation) { switch (orientation) { case Orientation.BL_TR: return GradientDrawable.Orientation.BL_TR; case Orientation.BOTTOM_TOP: return GradientDrawable.Orientation.BOTTOM_TOP; case Orientation.BR_TL: return GradientDrawable.Orientation.BR_TL; case Orientation.LEFT_RIGHT: return GradientDrawable.Orientation.LEFT_RIGHT; case Orientation.RIGHT_LEFT: return GradientDrawable.Orientation.RIGHT_LEFT; case Orientation.TL_BR: return GradientDrawable.Orientation.TL_BR; case Orientation.TOP_BOTTOM: return GradientDrawable.Orientation.TOP_BOTTOM; case Orientation.TR_BL: return GradientDrawable.Orientation.TR_BL; default: break; } return GradientDrawable.Orientation.TOP_BOTTOM; } private static void setRingValue(GradientDrawable drawable, Float thickness, Float thicknessRatio, Float innerRadius, Float innerRadiusRatio) { try { Field mGradientState = drawable.getClass().getDeclaredField("mGradientState"); mGradientState.setAccessible(true); Class mGradientStateClass = mGradientState.get(drawable).getClass(); Field mUseLevelForShape = mGradientStateClass.getDeclaredField("mUseLevelForShape"); mUseLevelForShape.setAccessible(true); mUseLevelForShape.setBoolean(mGradientState.get(drawable), false); if (thickness != null) { Field mThickness = mGradientStateClass.getDeclaredField("mThickness"); mThickness.setAccessible(true); mThickness.setInt(mGradientState.get(drawable), dip2px(thickness)); } if (thicknessRatio != null) { Field mThicknessRatio = mGradientStateClass.getDeclaredField("mThicknessRatio"); mThicknessRatio.setAccessible(true); mThicknessRatio.setFloat(mGradientState.get(drawable), dip2px(thicknessRatio)); } if (innerRadius != null) { Field mInnerRadius = mGradientStateClass.getDeclaredField("mInnerRadius"); mInnerRadius.setAccessible(true); mInnerRadius.setInt(mGradientState.get(drawable), dip2px(innerRadius)); } if (innerRadiusRatio != null) { Field mInnerRadiusRatio = mGradientStateClass.getDeclaredField("mInnerRadiusRatio"); mInnerRadiusRatio.setAccessible(true); mInnerRadiusRatio.setFloat(mGradientState.get(drawable), dip2px(innerRadiusRatio)); } } catch (NoSuchFieldException | IllegalAccessException t) { t.printStackTrace(); } } private static int dip2px(float dipValue) { final float scale = Resources.getSystem().getDisplayMetrics().density; return (int) (dipValue * scale + .5f); } @IntDef({ ShapeMode.RECTANGLE, ShapeMode.OVAL, ShapeMode.LINE, ShapeMode.RING, }) @Retention(RetentionPolicy.SOURCE) public @interface ShapeMode { int RECTANGLE = GradientDrawable.RECTANGLE; int OVAL = GradientDrawable.OVAL; /** * 画线时,有几点特性必须要知道的: * 1. 只能画水平线,画不了竖线; * 2. 线的高度是通过stroke的android:width属性设置的; * 3. size的android:height属性定义的是整个形状区域的高度; * 4. size的height必须大于stroke的width,否则,线无法显示; * 5. 线在整个形状区域中是居中显示的; * 6. 线左右两边会留有空白间距,线越粗,空白越大; * 7. 引用虚线的view需要添加属性android:layerType,值设为"software",否则显示不了虚线。 */ int LINE = GradientDrawable.LINE; int RING = GradientDrawable.RING; } @IntDef({ GradientType.LINEAR, GradientType.RADIAL, GradientType.SWEEP }) @Retention(RetentionPolicy.SOURCE) public @interface GradientType { int LINEAR = 0; int RADIAL = 1; int SWEEP = 2; } @IntDef({ Orientation.TOP_BOTTOM, Orientation.TR_BL, Orientation.RIGHT_LEFT, Orientation.BR_TL, Orientation.BOTTOM_TOP, Orientation.BL_TR, Orientation.LEFT_RIGHT, Orientation.TL_BR }) @Retention(RetentionPolicy.SOURCE) public @interface Orientation { int TOP_BOTTOM = 0; int TR_BL = 1; int RIGHT_LEFT = 2; int BR_TL = 3; int BOTTOM_TOP = 4; int BL_TR = 5; int LEFT_RIGHT = 6; int TL_BR = 7; } @Retention(RetentionPolicy.SOURCE) @Target({PARAMETER, FIELD}) @interface DP { } public static class ProxyDrawable extends StateListDrawable { private Drawable originDrawable; @Override public void addState(int[] stateSet, Drawable drawable) { if (stateSet != null && stateSet.length == 1 && stateSet[0] == 0) { originDrawable = drawable; } super.addState(stateSet, drawable); } Drawable getOriginDrawable() { return originDrawable; } } }