網站首頁 編程語言 正文
說明
compose中我們的所有ui操作,包括一些行為,例如:點擊、手勢等都需要使用Modifier來進行操作。因此對Modifier的理解可以幫助我們解決很多問題的
自定義星行Modifier
本文我們打算自定義一個Modifier,通過這個modifier我們可以實現用一個操作符就畫出五角星的效果
原理
我們實現繪制五角星的原理如下圖,首先我們會虛構兩個圓,將內圓和外圓角度平分五份,然后依次連接內圓和外圓的切點的坐標,然后使用path繪制完成。
實現
代碼中的實現涉及到自定義繪制,難度并不大。需要注意的點:
- composse中角度的錨點是弧度(Math.PI)、而原生的錨點是角度(360)
- 默認的原點在左上角,我們繪制的時候需要主動移動到組合的中心點
- 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,//星的數量
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 //五角星內圓半徑
val startAngle = (-Math.PI / 2).toFloat() //開始繪制點的外徑角度
val perAngle = (2 * Math.PI / starCount).toFloat() //兩個五角星兩個角直接的角度差
val outAngles = (0 until starCount).map {
val angle = it * perAngle + startAngle
Offset(radiusOuter * cos(angle), radiusOuter * sin(angle))
}//所有外圓角的頂點
val innerAngles = (0 until starCount).map {
val angle = it * perAngle + perAngle / 2 + startAngle
Offset(radiusInner * cos(angle), radiusInner * sin(angle))
}//所有內圓角的頂點
val path = Path()//繪制五角星的所有內圓外圓的點連接線
(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)//移動到內圓角的端點
path.lineTo(outAngles[(index + 1) % starCount].x,
outAngles[(index + 1) % starCount].y)//連接到下一個外圓角的端點
}
if (index == starCount - 1) {
path.close()
}
}
translate(size.width / 2, size.height / 2) {
drawPath(path, color, style = if (checked) Fill else Stroke(width = 5f))
}
}
}
最終實現效果
原文鏈接:https://blog.csdn.net/ymeddmn/article/details/124211249
相關推薦
- 2022-06-02 Android實現水平帶刻度的進度條_Android
- 2022-10-14 Linux環境conda虛擬環境中python解釋器對應問題 + 解決后pip install 路徑
- 2022-08-26 Python中CSV文件(逗號分割)實戰操作指南_python
- 2022-04-05 C語言用遞歸函數實現漢諾塔_C 語言
- 2022-08-05 C語言示例講解switch分支語句的用法_C 語言
- 2023-03-22 利用tkinter改變下拉列表(Combobox)的選項值_python
- 2022-08-17 Docker中的COPY指令和ADD指令詳解_docker
- 2023-03-20 C#如何遠程讀取服務器上的文本內容_C#教程
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支