0

我有一个继承自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 定义的漂亮分布,在第二种情况下,所有在左边界处对齐。

在这两种情况下,布局都是全宽的,我可以通过设置背景颜色来证明这一点。

我的代码中缺少什么?

4

1 回答 1

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 中整体设计它。

在我用克隆的对象实际填充布局之前,我以编程方式删除了模板。通过这种方法,我只需要为每个视图类维护一个布局文件。(构造函数的配置发生在封闭视图的布局文件中。)

于 2018-02-27T13:42:48.940 回答