How to extend ConstraintLayout in Kotlin

I’m trying to extend ConstraintLayout for use with a compound component in Kotlin. Most of the examples I’ve found are similar to this one, where the constructor has 3 parameters. However, there’s a fourth constructor that takes another parameter, defStyleRes. What’s the correct default value to use for it? Based on this I think 0 works, similar to defStyleAttr. Here is what I think the final code should look like:

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)

Answer

tl;dr: You can use 0 for the third and fourth arguments, but in my opinion you are better off just exposing a two-argument constructor and calling into the superclass’s own two-argument constructor.


When inflating a view from XML, only the two-argument constructor is ever called. Therefore, the one-, three-, and four-argument constructors are only relevant if you call them from Java/Kotlin code.

If you look at, for example, the source code for MaterialButton, you will find that its two-argument constructor looks like this:

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

And it has a corresponding three-argument constructor:

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

It does not specify a four-argument constructor at all.

The benefit of setting things up this way comes in two parts.

  1. You can style all MaterialButton instances in your app by specifying the materialButtonStyle attribute in your theme. See this documentation for more (search for “using default style theme attributes”).
  2. Future developers can subclass MaterialButton and specify a different default style attribute in their two-argument constructors:
public class MySpecialButton extends MaterialButton {

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

    // ...
}

If you do not care about these default styles/attributes, you can ignore the three- and four-argument constructors altogether, and simply call through to the parent’s two-argument constructor:

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

Leave a Reply

Your email address will not be published. Required fields are marked *