这不是问题的直接答案。仍然没有直接的答案。这个答案的类型是“采取更好的方法!”。
当一个问题的答案很少或没有答案时,我通常走在一条很少有人去的轨道上。然后有他们不这样做的原因。
我以编程方式将视图嵌套在其他视图中的方法很酷,但事实证明,如果不使用布局就很难做到这一点。以编程方式设置配置的所有好处太昂贵了,这可以在布局中轻松完成。Android 的 API 并没有为此做好充分的准备。
所以我转而使用方法,基于布局创建视图类。这意味着,我使用布局的两个参数构造函数创建视图。
在封闭的视图类中,我不能再直接创建嵌套视图,因为没有构造函数。相反,我从布局中读取配置的视图。
我创建了一个小类来帮助提取布局的配置子部分:
public class Cloner {
LayoutInflater inflater;
int layoutId;
public Cloner of(Context context) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
return this;
}
public Cloner from(@LayoutRes Integer layoutId) {
this.layoutId = layoutId;
return this;
}
public View clone(@IdRes int id) {
assert inflater != null;
View layout = inflater.inflate(layoutId, null);
View view = layout.findViewById(id);
((ViewManager) view.getParent()).removeView(view);
return view;
}
}
它是这样使用的:
MultipleChoiceAnswerView mcav =
(MultipleChoiceAnswerView) new Cloner().of(getContext())
.from(layoutId).clone(R.id.multipleChoiceAnswerView);
mcav.plugModel(challenge.getAnswer());
这已经显示了我如何在第二步中连接模型,因为我无法再将它输入到构造函数中。
在构造函数中,我首先评估给定的属性。然后我通过扩展随附的第二个布局文件来设置视图,我没有在这里显示。因此涉及到两种布局,一种用于配置构造函数的输入,一种用于内部布局。
当调用plugModel
发生时,膨胀的内部布局被匹配给定模型的对象使用和扩展。同样,我不是以编程方式创建这些对象,而是从第三个(或第二个)布局文件中将它们作为模板读取。在上面给出的帮助下再次完成Cloner
。
private Button getButton(final Integer index, String choice) {
Button button = (Button) new Cloner().of(getContext()).from(layoutId).clone(R.id.button);
button.setId(generateViewId());
button.setText(choice);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
answer.choiceByIndex(index);
}
});
return button;
}
在实践中,我将此对象模板(如按钮)作为子项放入第二个布局文件中。所以我可以在 Android Studio Designer 中整体设计它。
在我用克隆的对象实际填充布局之前,我以编程方式删除了模板。通过这种方法,我只需要为每个视图类维护一个布局文件。(构造函数的配置发生在封闭视图的布局文件中。)