ok,这就是一个很简单的弹框,其中进度条、进度文字、进度标识图片这些因素是和进度搭边的,所以把他们单独抽取出来做成一个控件CarProgressView,先上代码:
package com.carfinanceapp.update
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import com.carfinanceapp.R
import com.carfinanceapp.utils.dp2px
class 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 Father
class 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.utils
import android.content.res.Resources
import 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代码,更优雅更快速的开发工程,有机会用就尽量用吧,不说了,准备下班溜了