Krz*_*mic 1 android android-ui android-layout
我有以下形状XML:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:a="http://schemas.android.com/apk/res/android"
a:shape="ring"
a:innerRadiusRatio="3"
a:thicknessRatio="8"
a:useLevel="false">
<!-- some other stuff goes here -->
</gradient>
</shape>
Run Code Online (Sandbox Code Playgroud)
我想用代码来创建这个形状,因为有些东西需要在我做之前动态计算,所以静态预定义布局不会削减它.
我是Android的新手,无法弄清楚XML如何转换为代码,并且没有继承自Shape的RingShape类.
除了回答这个问题之外,如果有一个指南可以详细说明XML和Java代码之间的关系以及如何处理XML以便最终在屏幕上显示,我也会感谢链接.谢谢.
MH.*_*MH. 12
鲁本已经指出了最有用的观察,所以我只关注故事的实施方面.使用反射的多种方法可能会为您提供所需的内容.
第一个是(ab)使用带有GradientState引用的私有GradientDrawable构造函数.不幸的是,后者是包含可见性的最终子类,因此您无法轻松访问它.为了使用它,您需要进一步深入使用反射或将其功能模仿到您自己的代码中.
第二种方法是使用反射来获取私有成员变量mGradientState,幸运的是它有一个getter形式getConstantState().这将为您提供ConstantState,它在运行时实际上是一个GradientState,因此我们可以使用反射来访问其成员并在运行时更改它们.
为了支持上述语句,这里有一个基本的实现,可以从代码中创建一个环形drawable:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
以上可以按如下方式用于从代码创建RingDrawable并将其显示在标准ImageView中.
ImageView target = (ImageView) findViewById(R.id.imageview);
RingDrawable ring = new RingDrawable(10, 20, 0, 0);
ring.setColor(Color.BLUE);
target.setImageDrawable(ring);
Run Code Online (Sandbox Code Playgroud)
这将在ImageView中显示一个简单的不透明蓝色环(内部半径为10个单位,厚度为20个单位).您需要确保不将ImageView的宽度和高度设置为wrap_content,除非您添加ring.setSize(width, height)上面的代码以便显示它.
希望这可以帮助你以任何方式.
Reu*_*ton 10
戒指和其他形状GradientDrawables.
如果查看GradientDrawable 的源代码,您会发现某些属性(如innerRadius)只能通过XML定义......它们不会通过访问器方法公开.相关状态对于类来说也是无用的,因此子类化也没有帮助.
| 归档时间: |
|
| 查看次数: |
12490 次 |
| 最近记录: |