首页 > 解决方案 > 如何在 Kotlin 中扩展 ConstraintLayout

问题描述

我正在尝试扩展 ConstraintLayout 以与 Kotlin 中的复合组件一起使用。我发现的大多数示例都与此类似,其中构造函数有 3 个参数。但是,还有第四个构造函数,它采用另一个参数 defStyleRes。使用它的正确默认值是什么?基于此,我认为 0 有效,类似于 defStyleAttr。这是我认为最终的代码应该是这样的:

class ClockButton @JvmOverloads constructor(
context: Context,
private val attributeSet: AttributeSet? = null,
private val defStyleAttr: Int = 0,
private val defStyleRes: Int = 0) : ConstraintLayout(context, attributeSet, defStyleAttr, defStyleRes)

标签: androidandroid-layoutkotlin

解决方案


tl; dr:您可以使用0第三个和第四个参数,但在我看来,您最好只公开一个双参数构造函数并调用超类自己的双参数构造函数。


当从 XML 扩展视图时,只会调用两个参数的构造函数。因此,只有在 Java/Kotlin 代码中调用一、三和四参数构造函数时,它们才有意义。

例如,如果您查看 的源代码MaterialButton,您会发现它的双参数构造函数如下所示:

public MaterialButton(@NonNull Context context, @Nullable AttributeSet attrs) {
    this(context, attrs, R.attr.materialButtonStyle);
}

它有一个对应的三参数构造函数:

public MaterialButton(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(wrap(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
    // approx. 30 lines omitted
}

它根本没有指定四参数构造函数。

以这种方式进行设置的好处分为两部分。

  1. 您可以通过在主题中指定属性MaterialButton来设置应用程序中所有实例的样式。materialButtonStyle有关更多信息,请参阅此文档(搜索“使用默认样式主题属性”)。
  2. 未来的开发人员可以在他们的两个参数构造函数中继承MaterialButton并指定不同的默认样式属性:
public class MySpecialButton extends MaterialButton {

    public MySpecialButton(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs, R.attr.mySpecialStyle);
    }

    // ...
}

如果您不关心这些默认样式/属性,则可以完全忽略三参数和四参数构造函数,而只需调用父级的两参数构造函数:

class MyCompoundView(context: Context, attrs: AttributeSet) : ConstraintLayout(context, attrs)

推荐阅读