开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 13 天,点击查看活动详情
楔子
昨天我们刚刚看了一下Kotlin高阶函数(安卓开发之Kotlin学习——初遇高阶函数 - 掘金 (juejin.cn)),今天理应去继续研究与深入,但由于作者工作一天没去补充高阶函数知识,无法填坑,所以决定将后续改到周日。
本篇我们来看看Kotlin语言版的自定义View,之前一直看到Kotlin的自定义View就不想做。但在这段时间看了一些关于Kotlin自定义View的文章后,我感觉可以稍微写一下了。
之前评论区的小伙伴好像还想看画动画,如果用Java我似乎没有问题的,但在家里我主要坚持用Kotlin来写安卓,所以Kotlin面对=向对象方面的语法不熟让我一直对Kotlin的类的构造函数有点不适应,而继承View后的构造我之前没看别人写的我自己有点无从下手,更别说去draw了,而这次用自定义View后我很快就会去看看动画如何做,然后再出文章来分享。
自定义View
言归正传,我们还是继续看如何写自定义View。
View类的构造函数:
在Java中,我很熟练了,之前工作开发中已经写了不少自定义控件,从自定义进度条Progress到自定义倍数选择器然后到最近的摇杆控件,只要你多看看别人怎么去实现自定义的,然后把自己想要的控件给画好就成功大半,下面我们采用path路径draw方式去画一个爱心
Java实现对比
下面我们先看看Java的自定义View:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;
public class TestViewJava extends View {
public TestViewJava(Context context) {
super(context, null);
init();
}
public TestViewJava(Context context, AttributeSet attrs) {
super(context, attrs, 0);
init();
}
public TestViewJava(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private Paint paint;
private Path path;
void init() {
paint = new Paint();
path = new Path();
//抗锯齿
paint.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// paint.setColor(getResources().getColor(R.color.black));
// paint.setTextSize(36);
// canvas.drawText("Text Java", 200, 200, paint);
paint.setColor(getResources().getColor(R.color.red));
// canvas.drawCircle(50,50, 20, paint);
//使用路径画爱心
//弧形
// startAngle 是弧形的起始角度(x 轴的正向,即正右的方向,是 0 度的位置;顺时针为正角度,逆时针为负角度)
// sweepAngle 是弧形划过的角度
path.addArc(200, 200, 400, 400, -225, 225);
//画弧形
//forceMoveTo :是否留下移动的痕迹 true-无痕迹,false-留下痕迹
path.arcTo(400, 200, 600, 400, -180, 225, false);
// 从当前位置向目标位置画一条直线(当前位置,即最后一次调用画 Path 的方法的终点位置,初始值为原点 (0, 0))
// x 和 y 是目标位置的坐标
// 参数是绝对坐标
path.lineTo(400, 542);
canvas.drawPath(path, paint);
}
}
实现Kotlin自定义View
再看Kotlin的实现:
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.util.AttributeSet
import android.view.View
class TestView : View {
private var mPaint: Paint? = null
private var path: Path? = null
constructor(context : Context) : super(context, null) {
init()
}
constructor(context: Context, attrs: AttributeSet?) : super(context, null, 0) {
init()
}
constructor(context: Context, attrs: AttributeSet?, def : Int) : super(context, attrs, def) {
init()
}
private fun init() {
mPaint = Paint()
path = Path()
//抗锯齿
mPaint!!.isAntiAlias = true
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
//使用路径画爱心
path!!.addArc(200f, 200f, 400f, 400f, -225f, 225f)
path!!.arcTo(400f, 200f, 600f, 400f, -180f, 225f, false)
path!!.lineTo(400f, 542f)
canvas!!.drawPath(path!!, mPaint!!)
}
}
对比代码后,我们可以发现其实最主要就是构造函数的实现方式不一样,在Kotlin中我们使用关键字constructor构造,而Java中我们是使用与类名相同的方法(构造函数),而Koltin还多了空安全,且不用去new对象。 2/18勘正 上面的代码,昨晚作者在Activity中试图获取布局中添加的上述代码的id,然后出现空指针闪退的情况,所以代码做下面的调整:
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.util.AttributeSet
import android.view.View
class BallView : View {
private var mPaint : Paint? = null
private var path : Path? = null
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, defStyleAttr) {
initPaint()
}
private fun initPaint() {
mPaint = Paint()
path = Path()
//抗锯齿
mPaint!!.isAntiAlias = true
//防抖动
mPaint!!.isDither = true
}
override fun draw(canvas: Canvas?) {
super.draw(canvas)
mPaint!!.color = Color.RED
//使用路径画爱心
path!!.addArc(200f, 200f, 400f, 400f, -225f, 225f)
path!!.arcTo(400f, 200f, 600f, 400f, -180f, 225f, false)
path!!.lineTo(400f, 542f)
canvas!!.drawPath(path!!, mPaint!!)
}
}
我们增加了Paint的防抖动方法调用,然后主要是把次构造函数前两个的super改为this,最终指向最后一个构造,只需要在最后一个构造写init()初始化即可,这样放入布局加id后在Activity中可正常调用。
总体而言,写起来两者还是挺相似的,这也告诉作者只有动手才知道难度。
实现效果预览
我们将两个自定义View控件都放入布局,如果没有错误,我们在预览或者运行完成程序后就能看到效果图,如下:
尾声
实现了Kotlin的自定义View后,我也可以尝试用Kotlin去实现一些动画(希望没有什么语法障碍,明明说会Java开发安卓换Kotlin很容易,可能还是作者实践少了),比如之前我用CSS画的爱心效果(情人节专场——爱心动画 - 掘金 (juejin.cn)),我们理论上在安卓上也可以实现相同效果,先让作者看看应该用哪种动画模式,后面实现再分享出来。