使用Kotlin创建自定义View

Posted by newstrong on May 14, 2020

使用Kotlin创建自定义View

通过Android Studio点击 New-Kotlin Class/Files 创建的一个类,指定它实现一个View,例如:FrameLayout。此时IDE会提示你需要实现它的构造方法,Alert+Enter 即可,完成后如下:

1
2
3
class CustomViewTest(context: Context) : FrameLayout(context) {

}

此时只实现了View的一个构造方法,在代码中初始化并使用并没有问题,但是不能再XML中引用,因为自定义View需要实现类似以下的构造方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class CustomViewTest extends FrameLayout {
    public CustomViewTest(@NonNull Context context) {
        super(context);
    }

    public CustomViewTest(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomViewTest(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public CustomViewTest(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }
}

还好Kotlin有constructor关键字,用来在类名后指定主构造方法,或者单独在类中,指定次级构造方法。

1
2
3
4
5
6
7
class CustomViewTest: FrameLayout {
    constructor(context: Context):this(context,null)

    constructor(context: Context, attrs: AttributeSet?) : this(context,attrs,0)

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

上面的写法其实不是很好看,不太符合Kotlin极简思想,请参考更简单的实现:

1
2
3
class CustomViewTest @JvmOverloads constructor(context: Context,attrs:AttributeSet?,defStyleAttr: Int=0): FrameLayout(context,attrs,defStyleAttr) {
    
}

是不是够极简,但是在Java调用这个类的构造方法时候,因为Java没有默认参数的这种写法,需要全部指定所有的参数。

结论:全局Kotlin,使用最后一种极简的写法,Java-Kotlin混编,特别是需要Java初始化Kotlin自定义View,则使用Constructor写法。


原文:

https://antonioleiva.com/custom-views-android-kotlin/