😭

カスタムViewクラスをJavaからKotlinにコンバートしたら謎のレイアウト崩れが発生したよ〜😭うぇ〜ん

2023/06/30に公開

今のプロジェクトではJava:Kotlinの比率がおおよそ20:80くらいで、日々JavaコードをKotlin化するpull-requestが作られています。プロジェクトでは、EditTextを継承したカスタムEditTextを利用していました。ある日このカスタムEditTextをKotlin化することになり、いくつかの段階を踏んで安全に実装、マージをしていたところ…、最後のpull-requestで謎のレイアウト崩れが発生しました。

googleのissue truckerにも 挙げられている ようなのですが、もう少し具体的に書きます。

class CustomEditText : TextInputEditText {

    constructor(context: Context?)
        : super(context)
    constructor(context: Context, attrs: AttributeSet)
        : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet, defStyle: Int)
        : super(context, attrs, defStyle)
}

コンストラクタをオーバーロードしているので、これらをアノテーション@JvmOverloadsを使って、まとめます。

class CustomEditText @JvmOverloads constructor(
    context: Context?,
    attrs: AttributeSet? = null,
    defStyle: Int = 0
) : TextInputEditText(context, attrs, defStyle) {

    // constructor(context: Context?) :
    //     super(context)
    // constructor(context: Context, attrs: AttributeSet) :
    //     super(context, attrs)
    // constructor(context: Context, attrs: AttributeSet, defStyle: Int) :
    //     super(context, attrs, defStyle)
    
}

こうなります。
CustomEditText1 = @JvmOverloads(黄色)
CustomEditText2 = constructor 3つ(水色)

これを解決するには、@JvmOverloadsでまとめたコンストラクタのdefStyleにandroid標準のスタイルを指定するか、

class CustomEditText @JvmOverloads constructor(
    context: Context?,
    attrs: AttributeSet? = null,
    defStyle: Int = android.xxx.yyy.R.attr.editTextStyle // ここ
) : TextInputEditText(context, attrs, defStyle) {

    // constructor(context: Context?) :
    //     super(context)
    // constructor(context: Context, attrs: AttributeSet) :
    //     super(context, attrs)
    // constructor(context: Context, attrs: AttributeSet, defStyle: Int) :
    //     super(context, attrs, defStyle)
}

もしくは constructor 記述に戻す

class CustomEditText : TextInputEditText {

    constructor(context: Context?)
        : super(context)
    constructor(context: Context, attrs: AttributeSet)
        : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet, defStyle: Int)
        : super(context, attrs, defStyle)
}

Discussion