Kotlin编写自定义控件复习笔记

最近一年在公司要么写React Native,要么写前端WEB,好久没有写安卓原生代码和Kotlin了,刚刚来了个需求,RN项目安卓端更新不用跳转应用市场,直接通过后台的url下载apk,下载apk的时候进度条是定制的,如图:
更新UI图

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)
    }
}
  1. 重载方法注解 @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就行了

  1. 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()

  1. init初始化代码块
    kotlin把构造方法的参数声明在类名后面了,也没有构造方法的fun,所以类创建的时候需要初始化的代码就要写在init{...}里面
  2. 扩展方法
    这个就好玩了,比如我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代码,更优雅更快速的开发工程,有机会用就尽量用吧,不说了,准备下班溜了

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容