日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無(wú)先后,達(dá)者為師

網(wǎng)站首頁(yè) 編程語(yǔ)言 正文

利用Jetpack?Compose實(shí)現(xiàn)繪制五角星效果_Android

作者:安安安安卓 ? 更新時(shí)間: 2022-06-16 編程語(yǔ)言

說(shuō)明

compose中我們的所有ui操作,包括一些行為,例如:點(diǎn)擊、手勢(shì)等都需要使用Modifier來(lái)進(jìn)行操作。因此對(duì)Modifier的理解可以幫助我們解決很多問(wèn)題的

自定義星行Modifier

本文我們打算自定義一個(gè)Modifier,通過(guò)這個(gè)modifier我們可以實(shí)現(xiàn)用一個(gè)操作符就畫(huà)出五角星的效果

原理

我們實(shí)現(xiàn)繪制五角星的原理如下圖,首先我們會(huì)虛構(gòu)兩個(gè)圓,將內(nèi)圓和外圓角度平分五份,然后依次連接內(nèi)圓和外圓的切點(diǎn)的坐標(biāo),然后使用path繪制完成。

實(shí)現(xiàn)

代碼中的實(shí)現(xiàn)涉及到自定義繪制,難度并不大。需要注意的點(diǎn):

  1. composse中角度的錨點(diǎn)是弧度(Math.PI)、而原生的錨點(diǎn)是角度(360)
  2. 默認(rèn)的原點(diǎn)在左上角,我們繪制的時(shí)候需要主動(dòng)移動(dòng)到組合的中心點(diǎn)
  3. path的繪制使用Fill可以填充閉合路徑圖形,使用Stroke可以繪制線性閉合路徑圖形

代碼


fun Modifier.customDraw(
    color: Color,
    starCount: Int = 5,
    checked: Boolean = false,
) =
    this.then(CustomDrawModifier(color, starCount, checked = checked))

class CustomDrawModifier(
    private val color: Color,
    private val starCount: Int = 5,//星的數(shù)量
    private var checked: Boolean = false,
) :
    DrawModifier {
    override fun ContentDrawScope.draw() {
        log("$size")
        val radiusOuter = if (size.width > size.height) size.height / 2 else size.width / 2 //五角星外圓徑
        val radiusInner = radiusOuter / 2 //五角星內(nèi)圓半徑
        val startAngle = (-Math.PI / 2).toFloat() //開(kāi)始繪制點(diǎn)的外徑角度
        val perAngle = (2 * Math.PI / starCount).toFloat() //兩個(gè)五角星兩個(gè)角直接的角度差
        val outAngles = (0 until starCount).map {
            val angle = it * perAngle + startAngle
            Offset(radiusOuter * cos(angle), radiusOuter * sin(angle))
        }//所有外圓角的頂點(diǎn)
        val innerAngles = (0 until starCount).map {
            val angle = it * perAngle + perAngle / 2 + startAngle
            Offset(radiusInner * cos(angle), radiusInner * sin(angle))
        }//所有內(nèi)圓角的頂點(diǎn)
        val path = Path()//繪制五角星的所有內(nèi)圓外圓的點(diǎn)連接線
        (0 until starCount).forEachIndexed { index, _ ->
            val outerX = outAngles[index].x
            val outerY = outAngles[index].y
            val innerX = innerAngles[index].x
            val innerY = innerAngles[index].y
//            drawCircle(Color.Red, radius = 3f, center = outAngles[index])
//            drawCircle(Color.Yellow, radius = 3f, center = innerAngles[index])
            if (index == 0) {
                path.moveTo(outerX, outerY)
                path.lineTo(innerX, innerY)
                path.lineTo(outAngles[(index + 1) % starCount].x,
                    outAngles[(index + 1) % starCount].y)
            } else {
                path.lineTo(innerX, innerY)//移動(dòng)到內(nèi)圓角的端點(diǎn)
                path.lineTo(outAngles[(index + 1) % starCount].x,
                    outAngles[(index + 1) % starCount].y)//連接到下一個(gè)外圓角的端點(diǎn)
            }
            if (index == starCount - 1) {
                path.close()
            }
        }
        translate(size.width / 2, size.height / 2) {
            drawPath(path, color, style = if (checked) Fill else Stroke(width = 5f))
        }
    }

}

最終實(shí)現(xiàn)效果

原文鏈接:https://blog.csdn.net/ymeddmn/article/details/124211249

欄目分類(lèi)
最近更新