作用图
始于进展条,但不终于进展条
我也不知道为啥要起个这么傻的标题。很屡次了,每次学习自定义view后,搞了一段时间就草草收场,这东西是这样的,自身不像咱们日常运用的比方什么一些个代码写法什么的,滚瓜烂熟。这自己写view一段时间不搞,感觉就不会了一样。再一个是,公司的管理人员不会等你磨磨唧唧的写完一个没有bug的view,所以我或许说大多数人一看到不常用的view,立刻就跑去百度,google,github上翻有没有现已写好的,命运好点,一些个开源作者现已把功用封装好了,拿来即用(以上做法我认为是正确的,可是对咱们自身是完全没有提高),横竖我是很少想过为什么这么完成,这也不重要,重要的是我没有自己去着手完成一遍。说了挺多废话的,现在开始功用的完成。如同都没扯到标题中的进展条???
免责声明
由于代码测验少,没封装,经不起检测,仅供学习。还有一个是作用是我学习的某篇文章的,可是我找不到原文了,抱愧。
功用思路
自身也没啥好说的,东西太简略了,就当写给还没触摸过的同学吧,有经历的同学完全能够跳过整篇文章或许学习一下compose中怎么完成。
我说下我的思路,有些同学反响快能够一步到位。首要需求将功用分化,千里之行,始于足下。
制作内部圆环和外部圆弧
Canvas(modifier = Modifier.size(300.dp), onDraw = {
val innerStrokeWidth = 10.dp.toPx()
val radius = 120.dp.toPx()
val outStrokeWidth = 17.dp.toPx()
val canvasWidth = size.width
val canvasHeight = size.height
//内部圆
drawCircle(
Color(222, 228, 246),
radius = radius,
center = Offset(canvasWidth / 2, canvasHeight / 2),
style = Stroke(innerStrokeWidth)
)
//圆弧进展
drawArc(
Color(46, 120, 249),
startAngle = -90f,
sweepAngle = 120f,
useCenter = false,
size = Size(radius * 2, radius * 2),
style = Stroke(outStrokeWidth, cap = StrokeCap.Round),
topLeft = Offset(center.x - radius, center.y - radius)
)
})
定义的变量从姓名应该比较简单看出来,需求留意的是.toPx()和.toDp()等这种便捷办法只有在DrawScope区域里也便是onDraw = { 区域 } 里才能运用。
drawCircle中Offset用于确认圆的圆心,size也是也是DrawScope区域内的特点,可获取Canvas尺度等信息,比方size.width获取的便是设置画布的宽度为300dp(转成像素)。
还一个重点是drawArc中的size和topLeft特点。咱们需求画的是圆弧,size用于确认制作的范围,所以天然就能够确认size是一个正方形。
却是这个topLeft我当时想了挺久到底是个啥,其实便是字面意思,让你指定:区域的左上角在哪里
有人能引荐下免费的好用的画图东西吗,自带的用着不舒服啊。
制作文字
目前drawText有四种办法,主要是两种,如下图12行为榜首种办法,34行为第二种办法
榜首种和第二种区别不大,主要是色彩是传递Brush仍是Color。
对着下方的一张图(drawText办法特点)和一份代码看:假如是运用的第二种办法,需求传递的榜首个参数为TextMeasurer,也便是val textMeasure = rememberTextMeasurer(),没有后边的measure(……)。运用这种办法有个当地需求留意,假如你需求设置文本的style特点,并且特点会导致文本的大小呈现改动,比方加粗,改动文本的sp,这个当地有个坑便是你在drawText()的时分,里边有个参数需求你设置style,当你设置了改动文字的style后,你认为没任何问题,成果你会发现写出来的UI和你的期望有误差,这儿需求别的调用textMeasure.measure(….),里边再设置一遍你的style,比较的费事。所以我仍是引荐我下面这种写法,假如没理解我在说什么,能够自己在编辑器里对着drawText特点看一下,光看不做假把式。
val textPercent = "60%"
//丈量文字
val textPercentLayResult = rememberTextMeasurer().measure(
text = AnnotatedString(textPercent),
style = TextStyle(
color = Color(96, 98, 172),
fontSize = 30.sp,
fontWeight = FontWeight.Bold
)
)
Canvas(modifier = Modifier.size(300.dp), onDraw = {
val canvasWidth = size.width
val canvasHeight = size.height
val textPercentWidth = textPercentLayResult.size.width
val textPercentHeight = textPercentLayResult.size.height
//百分比文字
drawText(
textLayoutResult = textPercentLayResult,
topLeft = Offset(
canvasWidth / 2 - textPercentWidth / 2,
canvasHeight / 2 - textPercentHeight
),
)
})
topLeft的特点现已很明显了,刚才讲圆弧的时分讲过了,便是榜首个文字的左上方,其他的变量名也比较简单知道用途
动画作用
在compose里的动画作用(不止动画)比较原生真的是简单太多了
//sweepState便是外部传进来的百分比,比方最大是100,
当时是60,那么sweepState便是0.6,目标值便是360*0.6=60,
所以扫过的视点animAngle便是60度。
val animAngle = animateFloatAsState(
targetValue = sweepState.value * 360,
animationSpec = tween(1000)
)
//0.6 * 100 = 60便是咱们显现的百分比
val animPercent = animateIntAsState(
targetValue = (sweepState.value * 100).toInt(),
animationSpec = tween(1000)
)
//赋值给textPercent,传递到要丈量的文本中
val textPercent = "${animPercent.value}%"
val textPercentLayResult = rememberTextMeasurer().measure(
text = AnnotatedString(textPercent),
。。。
)
drawArc(
。。。
sweepAngle = animAngle.value,
。。。
)
animateFloatAsState的第二个参数是装备动画的特点,有爱好能够看下他人的文章了解下有哪些动画装备特点,横竖我是记不清。 出勤率的制作没啥好说,就单纯是个文本比较简略,同“百分比”文字
源码
@Composable
fun Progress() {
val sweepState = remember {
mutableStateOf(0f)
}
val max = 100f
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.height(20.dp))
ProgressBarView(sweepState)
Spacer(modifier = Modifier.height(20.dp))
Button(onClick = {
sweepState.value = Random.nextInt(1 until 99) / max
}) {
Text(text = "按钮")
}
}
}
@OptIn(ExperimentalTextApi::class)
@Composable
private fun ProgressBarView(sweepState: MutableState<Float>) {
val animAngle = animateFloatAsState(
targetValue = sweepState.value * 360,
animationSpec = tween(1000)
)
val animPercent = animateIntAsState(
targetValue = (sweepState.value * 100).toInt(),
animationSpec = tween(1000)
)
val textPercent = "${animPercent.value}%"
val textPercentLayResult = rememberTextMeasurer().measure(
text = AnnotatedString(textPercent),
style = TextStyle(
color = Color(96, 98, 172),
fontSize = 30.sp,
fontWeight = FontWeight.Bold
)
)
val textDesc = "出勤率"
val textDescLayoutResult = rememberTextMeasurer().measure(
AnnotatedString(textDesc),
TextStyle(color = Color(178, 193, 209))
)
Canvas(modifier = Modifier.size(300.dp), onDraw = {
val innerStrokeWidth = 10.dp.toPx()
val radius = 120.dp.toPx()
val outStrokeWidth = 17.dp.toPx()
val canvasWidth = size.width
val canvasHeight = size.height
//内部圆
drawCircle(
Color(222, 228, 246),
radius = radius,
center = Offset(canvasWidth / 2, canvasHeight / 2),
style = Stroke(innerStrokeWidth)
)
//圆弧进展
drawArc(
Color(46, 120, 249),
startAngle = -90f,
sweepAngle = animAngle.value,
useCenter = false,
size = Size(radius * 2, radius * 2),
style = Stroke(outStrokeWidth, cap = StrokeCap.Round),
topLeft = Offset(center.x - radius, center.y - radius)
)
val textPercentWidth = textPercentLayResult.size.width
val textPercentHeight = textPercentLayResult.size.height
//百分比文字
drawText(
textLayoutResult = textPercentLayResult,
topLeft = Offset(
canvasWidth / 2 - textPercentWidth / 2,
canvasHeight / 2 - textPercentHeight
),
)
val textDescWidth = textDescLayoutResult.size.width
val textDescHeight = textDescLayoutResult.size.height //用不着
//出勤率
drawText(
textLayoutResult = textDescLayoutResult,
topLeft = Offset(
canvasWidth / 2 - textDescWidth / 2,
canvasHeight / 2
),
)
})
}
最后
如同看起来完成的代码量好多一样,其实假如不换行的话真没几行,比较原生的完成我只想说:咱们compose太厉害啦。下课
学到东西的同学点点重视,学习进步不走失