Kotlin自定義 View - 畫一個雷達(dá)掃描界面

概述

在前幾期自定義 View的文章里哎垦,有一篇是畫了一個雷達(dá)掃描界面武通。這次再重畫一遍县好,用 Kotlin畫。因?yàn)檫壿嬙砼c上次畫的一樣,只是換了科特林鳖粟。所以原理這里就不講了,就直接貼出代碼拙绊。在代碼注釋里有部分Kotlin區(qū)別于java的語法解釋向图,自己看就好。

Screenrecorder-2021-08-04-18-15-57-5262021842252183.gif

代碼:

class ScanViewKt : View {
    // 同心圓畫筆
    private lateinit var paint: Paint  // 注釋 1标沪, lateinit關(guān)鍵詞 :可延遲賦值榄攀。 var關(guān)鍵詞 :可變變量聲明(val 則類似于 java的 final)

    // 畫掃描圓畫筆
    private lateinit var scanPaint: Paint  // 注釋 2,變量名在前金句,類型在后檩赢,中間引號

    // 設(shè)備點(diǎn)畫筆
    private lateinit var pointPaint: Paint  // 注釋 3,后面分號可以省略违寞,但必須換行贞瞒,否則下一條語句報(bào)錯

    // 同心圓之間的間距
    private var spaceIntCircles: Int = 0

    // 掃描圓的陰影
    private lateinit var scanShader: Shader

    // 掃描圓陰影矩陣
    private var scanMatrix: Matrix = Matrix() // 注釋 4偶房,對象創(chuàng)建不用 java的 new關(guān)鍵詞了

    // 旋轉(zhuǎn)角度
    private var rotation: Int = 0

    // 掃描結(jié)果
    private var pointList: CopyOnWriteArrayList<PointPositionKt> = CopyOnWriteArrayList()

    // 停止掃描
    private var stopScan = false

    constructor(context: Context) : this(context, null) // 注釋 5,構(gòu)造器關(guān)鍵詞 constructor

    constructor(context: Context, attrs: AttributeSet?) : this(
        context,
        attrs,
        0
    ) // 注釋 6军浆,構(gòu)造器調(diào)用的 this棕洋、super放在形參表和方法體之間,加以引號

    constructor(context: Context, attrs: AttributeSet?, style: Int) : super(context, attrs, 0) {
        init()
    }

    private fun init() {   // 注釋 7乒融, 方法用關(guān)鍵字 fun修飾
        paint = Paint()
        paint.style = Paint.Style.STROKE
        paint.color = Color.parseColor("#FFF10404")
        paint.isDither = true
        paint.isAntiAlias = true
        paint.strokeWidth = 2f

        scanPaint = Paint()
        scanPaint.isDither = true
        scanPaint.isAntiAlias = true

        pointPaint = Paint()
        pointPaint.style = Paint.Style.FILL
        pointPaint.isDither = true
        pointPaint.isAntiAlias = true
        pointPaint.color = Color.parseColor("#FF3700B3")
    }

    override fun onMeasure(
        widthMeasureSpec: Int,
        heightMeasureSpec: Int
    ) {  //注釋 8掰盘, 重寫的方法聲明使用關(guān)鍵字 override替換注解
        var width = getMeasureSize(widthMeasureSpec)
        var height = getMeasureSize(heightMeasureSpec)
        var size = Math.min(width, height)
        setMeasuredDimension(size, size)
    }

    @SuppressLint("DrawAllocation")
    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        spaceIntCircles = width / 12 - width / 120
        scanShader = SweepGradient(
            (width / 2).toFloat(), (height / 2).toFloat(),
            intArrayOf(Color.TRANSPARENT, Color.GRAY), floatArrayOf(0.1f, 0.9f)
        )
        scanPaint.shader = scanShader
        scanShader.setLocalMatrix(scanMatrix)
    }

    private fun getMeasureSize(measureSpec: Int): Int {
        var mode = MeasureSpec.getMode(measureSpec)
        var size = MeasureSpec.getSize(measureSpec)
        if (mode == AT_MOST) return dipToPx(18f).toInt()  // 注釋 9,類型強(qiáng)轉(zhuǎn)使用 to..()方法
        return size
    }

    private fun dipToPx(dip: Float): Float {  // 注釋 10簇抵,方法返回值類型方法形參列表后庆杜,以引號隔開
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, dip, resources.displayMetrics)
    }

    override fun onDraw(canvas: Canvas) {
        // 畫 6個圈
        for (i in 0..6) {  // 注釋 11,for循環(huán)的其中一種形式: (i in 0..6)碟摆,0..6 表示區(qū)間晃财。這里包含邊界值〉渫桑可用  (i in 0 until 6)去除有邊界
            canvas.drawCircle(
                (height / 2).toFloat(), (height / 2).toFloat(),
                (i * spaceIntCircles).toFloat(), paint
            )
        }
        // 畫帶陰影的掃描圓
        canvas.drawCircle(
            (height / 2).toFloat(), (height / 2).toFloat(),
            (5 * spaceIntCircles).toFloat(), scanPaint
        )
        drawPoint(canvas)
        setRotation()
    }

    /***
     * 畫所有的點(diǎn) (設(shè)備)
     * ***/
    private fun drawPoint(canvas: Canvas) {
        for (item in pointList) { // 注釋 12断盛, item關(guān)鍵字的 for循環(huán)迭代遍歷集合
            pointPaint.color = item.pointColor
            if (pointList.indexOf(item) == pointList.size - 1) {
                canvas.drawCircle(
                    item.getPoint().x, item.getPoint().y,
                    (spaceIntCircles / 2).toFloat(), pointPaint
                )
                continue
            }
            canvas.drawCircle(
                item.getPoint().x, item.getPoint().y,
                (spaceIntCircles / 4).toFloat(), pointPaint
            )
        }
    }
    /***
     * 改變旋轉(zhuǎn)角度
     * ***/
    private fun setRotation() {
        if (rotation >= 360) rotation = 0
        rotation += 2
        scanMatrix.setRotate(rotation.toFloat(), (width / 2).toFloat(), (height / 2).toFloat())
        scanShader.setLocalMatrix(scanMatrix)
        if (!stopScan) invalidate()
    }

    /***
     *停止掃描
     * ***/
    fun setScanStop() {
        if (this.stopScan) return
        this.stopScan = true
    }

    /***
     * 開始掃描
     * ***/
    fun setStartScan() {
        if (!this.stopScan) return
        this.stopScan = false
        invalidate()
    }

    /***
     * 添加設(shè)備
     * ***/
    fun addPoint(point: PointPositionKt) {
        if (stopScan) return
        if (this.pointList.contains(point)) return
        point.setRadio(spaceIntCircles * 6)
            .setCenterPoint(PointF((width / 2).toFloat(), (height / 2).toFloat()))
            .setPoint(rotation)
        pointList.add(point)
    }

    /***
     * 移除某個設(shè)備
     * ***/
    fun removePoint(point: PointPositionKt) {
        if (pointList.contains(point)) pointList.remove(point)
        invalidate()
    }

    /***
     * 清除界面設(shè)備
     * ***/
    fun clearPoint() {
        if (pointList.size == 0) return
        pointList.clear()
        invalidate()
    }
}

整理一下上面的語法注釋:

// 注釋 1, lateinit關(guān)鍵詞 :可延遲賦值愉舔。 var關(guān)鍵詞 :可變變量聲明(val 則類似于 java的 final)
// 注釋 2钢猛,變量名在前,類型在后轩缤,中間引號
// 注釋 3命迈,后面分號可以省略,但必須換行火的,否則下一條語句報(bào)錯
// 注釋 4壶愤,對象創(chuàng)建不用 java的 new關(guān)鍵詞了
// 注釋 5,構(gòu)造器關(guān)鍵詞 constructor
// 注釋 6馏鹤,構(gòu)造器調(diào)用的 this征椒、super放在形參表和方法體之間,加以引號
// 注釋 7湃累, 方法用關(guān)鍵字 fun修飾
// 注釋 8勃救, 重寫的方法聲明使用關(guān)鍵字 override替換注解
// 注釋 9,類型強(qiáng)轉(zhuǎn)使用 to..()方法
// 注釋 10治力,方法返回值類型放在形參列表后蒙秒,以引號隔開
// 注釋 11,for循環(huán)的其中一種形式: (i in 0..6)宵统,0..6 表示區(qū)間税肪。這里包含邊界值。可用  (i in 0 until 6)去除右邊界
// 注釋 12益兄, item關(guān)鍵字的 for循環(huán)迭代遍歷集合

源碼:畫一個雷達(dá)掃描控件

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锻梳,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子净捅,更是在濱河造成了極大的恐慌疑枯,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛔六,死亡現(xiàn)場離奇詭異荆永,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)国章,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門具钥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人液兽,你說我怎么就攤上這事骂删。” “怎么了四啰?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵宁玫,是天一觀的道長。 經(jīng)常有香客問我柑晒,道長欧瘪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任匙赞,我火速辦了婚禮佛掖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘涌庭。我一直安慰自己芥被,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布脾猛。 她就那樣靜靜地躺著撕彤,像睡著了一般鱼鸠。 火紅的嫁衣襯著肌膚如雪猛拴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天蚀狰,我揣著相機(jī)與錄音愉昆,去河邊找鬼。 笑死麻蹋,一個胖子當(dāng)著我的面吹牛跛溉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼芳室,長吁一口氣:“原來是場噩夢啊……” “哼专肪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起堪侯,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤嚎尤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后伍宦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體芽死,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年次洼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了关贵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡卖毁,死狀恐怖揖曾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情势篡,我是刑警寧澤翩肌,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站禁悠,受9級特大地震影響念祭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜碍侦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一粱坤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瓷产,春花似錦站玄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至尔邓,卻和暖如春晾剖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背梯嗽。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工齿尽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人灯节。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓循头,卻偏偏與公主長得像绵估,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子卡骂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容