我有一个继承自ConstraintLayout
的观点。在这个布局中,我使用ConstraintSet放置子项。
只要在构造函数外使用给定的AttributeSet
表单,它就可以工作:
public AnswerView(Context context, AttributeSet attrs) {
super(context, attrs);
如果我在没有attrs
可用时尝试分配布局,则无效。
public AnswerView(Context context) {
super(context);
setLayoutParams(new LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
在第一种情况下,子项得到一个漂亮的分布,就像ConstraintSet定义的那样,在第二种情况下,所有的行都在左边界处。
在这两种情况下,布局都会拉伸全宽,我可以通过设置背景颜色来证明。
我的代码中缺少什么?
答案 0 :(得分:0)
这不是问题的直接答案。直接答案仍然缺失。这个答案的类型是“采取更好的方法!”。
当问题很少或没有答案时,我通常会走上一条轨道,很少有人去。然后有理由说他们没有。
我在其他视图中以编程方式嵌套视图的方法很酷,但事实证明如果不使用布局就很难做到这一点。 以编程方式设置配置的所有好处太昂贵了,这可以在布局中轻松完成。 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中整体设计它。
以编程方式我在实际用克隆对象填充布局之前删除模板。通过这种方法,我只需要为每个视图类维护一个布局文件。 (构造函数的配置发生在封闭视图的布局文件中。)