Reuben 已经指出了最有用的观察结果,所以我将只关注故事的实施方面。有多种使用反射的方法可能会给你你正在寻找的东西。
第一个是(ab)使用接受 GradientState 引用的私有 GradientDrawable 构造函数。不幸的是,后者是具有包可见性的最终子类,因此您无法轻松访问它。为了使用它,您需要进一步深入使用反射或将其功能模仿到您自己的代码中。
第二种方法是使用反射获取私有成员变量mGradientState,好在有getConstantState()形式的getter。这将为您提供 ConstantState,它在运行时实际上是一个 GradientState,因此我们可以使用反射来访问其成员并在运行时更改它们。
为了支持上述陈述,这里有一个从代码创建环形可绘制对象的基本实现:
RingDrawable.java
public class RingDrawable extends GradientDrawable {
private Class<?> mGradientState;
public RingDrawable() {
this(Orientation.TOP_BOTTOM, null);
}
public RingDrawable(int innerRadius, int thickness, float innerRadiusRatio, float thicknessRatio) {
this(Orientation.TOP_BOTTOM, null, innerRadius, thickness, innerRadiusRatio, thicknessRatio);
}
public RingDrawable(GradientDrawable.Orientation orientation, int[] colors) {
super(orientation, colors);
setShape(RING);
}
public RingDrawable(GradientDrawable.Orientation orientation, int[] colors, int innerRadius, int thickness, float innerRadiusRatio, float thicknessRatio) {
this(orientation, colors);
try {
setInnerRadius(innerRadius);
setThickness(thickness);
setInnerRadiusRatio(innerRadiusRatio);
setThicknessRatio(thicknessRatio);
} catch (Exception e) {
// fail silently - change to your own liking
e.printStackTrace();
}
}
public void setInnerRadius(int radius) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
if (mGradientState == null) mGradientState = resolveGradientState();
Field innerRadius = resolveField(mGradientState, "mInnerRadius");
innerRadius.setInt(getConstantState(), radius);
}
public void setThickness(int thicknessValue) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
if (mGradientState == null) mGradientState = resolveGradientState();
Field thickness = resolveField(mGradientState, "mThickness");
thickness.setInt(getConstantState(), thicknessValue);
}
public void setInnerRadiusRatio(float ratio) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
if (mGradientState == null) mGradientState = resolveGradientState();
Field innerRadiusRatio = resolveField(mGradientState, "mInnerRadiusRatio");
innerRadiusRatio.setFloat(getConstantState(), ratio);
}
public void setThicknessRatio(float ratio) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
if (mGradientState == null) mGradientState = resolveGradientState();
Field thicknessRatio = resolveField(mGradientState, "mThicknessRatio");
thicknessRatio.setFloat(getConstantState(), ratio);
}
private Class<?> resolveGradientState() {
Class<?>[] classes = GradientDrawable.class.getDeclaredClasses();
for (Class<?> singleClass : classes) {
if (singleClass.getSimpleName().equals("GradientState")) return singleClass;
}
throw new RuntimeException("GradientState could not be found in current GradientDrawable implementation");
}
private Field resolveField(Class<?> source, String fieldName) throws SecurityException, NoSuchFieldException {
Field field = source.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
}
}
Above 可以按如下方式从代码中创建一个 RingDrawable 并将其显示在标准 ImageView 中。
ImageView target = (ImageView) findViewById(R.id.imageview);
RingDrawable ring = new RingDrawable(10, 20, 0, 0);
ring.setColor(Color.BLUE);
target.setImageDrawable(ring);
这将在 ImageView 中显示一个简单的、不透明的蓝色环(内半径 10 个单位,厚 20 个单位)。您需要确保不要将 ImageView 的宽度和高度设置为 wrap_content,除非您在上面的代码中添加 ring.setSize(width, height) 以使其显示。
希望这对您有所帮助。