最近一年在公司要么写React Native,要么写前端WEB,好久没有写安卓原生代码和Kotlin了,刚刚来了个需求,RN项目安卓端更新不用跳转应用市场,直接通过后台的url下载apk,下载apk的时候进度条是定制的,如图:
更新UI图
ok,这就是一个很简单的弹框,其中进度条、进度文字、进度标识图片这些因素是和进度搭边的,所以把他们单独抽取出来做成一个控件CarProgressView,先上代码:
package com.carfinanceapp.updateimport android.content.Contextimport android.graphics.*import android.util.AttributeSetimport android.view.Viewimport com.carfinanceapp.Rimport com.carfinanceapp.utils.dp2pxclass CarProgressView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) { var progress = 0 set(value) { field = value invalidate() } private var numPaint = Paint(Paint.ANTI_ALIAS_FLAG) private var bgPaint = Paint(Paint.ANTI_ALIAS_FLAG) private var linePaint = Paint(Paint.ANTI_ALIAS_FLAG) private var carPaint = Paint(Paint.ANTI_ALIAS_FLAG) private var bgRect = RectF() private var lineRect = RectF() private val carBitmap = BitmapFactory.decodeResource(resources, R.drawable.ic_progress_car) init { numPaint.textAlign = Paint.Align.CENTER numPaint.textSize = 24f.dp2px() numPaint.color = Color.parseColor("#52D46E") bgPaint.color = Color.parseColor("#F0F0F0") linePaint.color = Color.parseColor("#52D46E") carPaint.isFilterBitmap = true } override fun onDraw(canvas: Canvas?) { super.onDraw(canvas) canvas ?: return canvas.drawText("$progress%", measuredWidth / 2f, 30f.dp2px(), numPaint) drawBg(canvas) drawProgress(canvas) drawCar(canvas) } private fun drawBg(canvas: Canvas) { bgRect.top = 50f.dp2px() bgRect.left = measuredWidth * 0.06f bgRect.right = measuredWidth * 0.94f bgRect.bottom = 55f.dp2px() canvas.drawRoundRect(bgRect, 5f.dp2px(), 5f.dp2px(), bgPaint) } private fun drawProgress(canvas: Canvas) { lineRect.top = 49.5f.dp2px() lineRect.left = measuredWidth * 0.06f lineRect.right = measuredWidth * 0.94f * progress / 100f lineRect.bottom = 55.5f.dp2px() canvas.drawRoundRect(lineRect, 5f.dp2px(), 5f.dp2px(), linePaint) } private fun drawCar(canvas: Canvas) { //start -5 end -35 canvas.drawBitmap(carBitmap, measuredWidth * 0.94f * progress / 100f - 5.dp2px() - (0.3f * progress).dp2px(), 45f.dp2px(), carPaint) } }
重载方法注解 @JvmOverloads
首先看类文件的开头,正常来说Kotlin继承父类或者是实现接口都是通过:来的,例如下面这些
//无参继承open class Fatherclass Test() : Father()//有参继承open class Father2(age: Int)class Test2(age: Int) : Father2(age)class Test3() : Father2(99)class Test4(age: Int) : Father2(99)
上面这些都是单构造方法,没有重载的,像安卓自定义View,继承于View就有四个重载方法,从最少传入Context,到最多传入Context,AttributeSet,defStyleAttr,defStyleRes这四个,Kotlin重载构造方法只需要使用@JvmOverloads constructor就可以了,而方法fun前面只用加 @JvmOverloads就行了
field成员变量自带get、set方法
看本类第一个成员变量:
var progress = 0 set(value) { field = value invalidate() }
kotlin默认所有成员变量和方法都是public的,如果不想要public,得加上private,声明变量使用var或者val,一个可变一个类似于final不可变
所以第一行var progress = 0等价于java代码:int progress = 0且有两个public的方法,一个getProgress,一个getProgress
下面的 set(value) {...}就是重写了这个默认提供的set方法,加了一个刷新界面显示的invalidate()
init初始化代码块
kotlin把构造方法的参数声明在类名后面了,也没有构造方法的fun,所以类创建的时候需要初始化的代码就要写在init{...}里面扩展方法
这个就好玩了,比如我init代码中的第二行 :
numPaint.textSize = 24f.dp2px()
这里24f.dp2px()就是我给Float添加的扩展方法dp2px,扩展方法声明很简单,在任意kt文件里面都可以,去年一个项目中创建了一个NumberExtend.kt就直接拿来用了,里面就是各种dp和px互相转换的扩展方法,代码如下:
package com.carfinanceapp.utilsimport android.content.res.Resourcesimport android.view.ViewGroup/** * Created by liutanglei on 2017/11/4 */fun Int.dp2px(): Int { if (toInt() in intArrayOf(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)) { return this } return (this * (Resources.getSystem().displayMetrics.densityDpi / 160f)).toInt() } fun Int.px2dp(): Int { if (toInt() in intArrayOf(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)) { return this } val metrics = Resources.getSystem().displayMetrics return this / (metrics.densityDpi / 160) } fun Float.dp2px(): Float { if (toInt() in intArrayOf(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)) { return this } return this * (Resources.getSystem().displayMetrics.densityDpi / 160f) }
如上面所示,格式就是fun 类名.扩展方法名():返回值{扩展代码}
同理还有扩展属性,这里我没用使用,效果的话就是扩展一个没有属性,和这个类似
至于进度条控件的话,用画布画灰色的背景,绿色的进度,绿色的文字,还有汽车的图片,除了第一个,其他三个都要随着当前的progress改变,这些没什么好说的
对了,kotlin拼接字符串也很方便,"${变量}字符串" , 和es6里面的`${变量}字符串`有异曲同工之妙
写到这里马上就要下班了,总结一下就是kotlin能减少大量冗余的java代码,更优雅更快速的开发工程,有机会用就尽量用吧,不说了,准备下班溜了
作者:逆水行舟丶
链接:https://www.jianshu.com/p/627c42bbdd61
共同学习,写下你的评论
评论加载中...
作者其他优质文章