传统方法充满了样板代码和笨拙的资源处理。这就是我制作Spyglass framework 的原因。为了演示它是如何工作的,下面是一个示例,展示了如何制作一个显示字符串标题的自定义视图。
第 1 步:创建自定义视图类。
public class CustomView extends FrameLayout {
private TextView titleView;
public CustomView(Context context) {
super(context);
init(null, 0, 0);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs, 0, 0);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs, defStyleAttr, 0);
}
@RequiresApi(21)
public CustomView(
Context context,
AttributeSet attrs,
int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs, defStyleAttr, defStyleRes);
}
public void setTitle(String title) {
titleView.setText(title);
}
private void init(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
inflate(getContext(), R.layout.custom_view, this);
titleView = findViewById(R.id.title_view);
}
}
第二步:在values/attrs.xml资源文件中定义一个字符串属性:
<resources>
<declare-styleable name="CustomView">
<attr name="title" format="string"/>
</declare-styleable>
</resources>
第 3 步:将 @StringHandler 注释应用到 setTitle 方法,以告诉 Spyglass 框架在视图膨胀时将属性值路由到此方法。
@HandlesString(attributeId = R.styleable.CustomView_title)
public void setTitle(String title) {
titleView.setText(title);
}
现在您的类有一个 Spyglass 注释,Spyglass 框架将在编译时检测到它并自动生成 CustomView_SpyglassCompanion 类。
第四步:在自定义视图的init方法中使用生成的类:
private void init(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
inflate(getContext(), R.layout.custom_view, this);
titleView = findViewById(R.id.title_view);
CustomView_SpyglassCompanion
.builder()
.withTarget(this)
.withContext(getContext())
.withAttributeSet(attrs)
.withDefaultStyleAttribute(defStyleAttr)
.withDefaultStyleResource(defStyleRes)
.build()
.callTargetMethodsNow();
}
就是这样。现在,当您从 XML 实例化类时,Spyglass 伴侣会解释属性并进行所需的方法调用。例如,如果我们对以下布局进行膨胀,那么 setTitle 将被调用,并以 "Hello, World!" 作为参数。
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:width="match_parent"
android:height="match_parent">
<com.example.CustomView
android:width="match_parent"
android:height="match_parent"
app:title="Hello, World!"/>
</FrameLayout>
该框架不限于字符串资源,它有许多不同的注释来处理其他资源类型。如果您的方法有多个参数,它还具有用于定义默认值和传入占位符值的注释。
查看 Github 存储库以获取更多信息和示例。