compose已经发布好久了,还没有用过compose写过UI,之前只是在官网上了解过,看着这可组合函数嵌套,我就脑袋大,更Flutter一个德行,我的内心是抵触的,还是觉得用XML写香,抱着试一试的心态,打算用compose应用于实际项目中。(还是得多接触,多学习,真的是很香YYDS)
上图,测试:通过滑动slider也是安卓称ProgressBar来改变速度
@Composable
fun SpeedContent(){
//添加数字动画,避免速度变化过于突兀
var mytargetValue by remember { mutableStateOf(0) }
val progressInt: Int by animateIntAsState(targetValue = mytargetValue)
Column(modifier = Modifier
.background(color = Color.White)
.fillMaxSize(),
verticalArrangement = Arrangement.Bottom,
horizontalAlignment = Alignment.CenterHorizontally) {
Slider(value = mytargetValue.toFloat(),
onValueChange = {
mytargetValue = it.toInt() },
modifier = Modifier.fillMaxWidth(),
valueRange = 0f..180f)
SpeederMeter(progressInt)
}
}
具体实现
@OptIn(ExperimentalTextApi::class)
@Composable
fun SpeederMeter(speedNum: Int,modifier: Modifier = Modifier
.width(220.dp)
.height(120.dp)
.background(color = Color.White)){
val centerPointColor = Color.Blue
val colorCenterPoint1 = Color(0xFF000000)
val colorCenterPoint2 = Color(0xFFEE3E07)
val mersure = rememberTextMeasurer()
fun getPointX(centerX:Float,angle:Int,circleRdius:Float,step:Int):Float{
val angles = (angle*step).toDouble()
val angle = Math.toRadians(angles)
return centerX - cos(angle).toFloat()*(circleRdius)
}
fun getPointY(centerY:Float,angle:Int,circleRdius:Float,step:Int):Float{
val angles = (angle*step).toDouble()
val angle = Math.toRadians(angles)
return centerY- sin(angle).toFloat()*(circleRdius)
}
val myUnit = "KM/H"
val speedTextList = Array(7){(it*20).toString()}
Box(modifier,
contentAlignment = Alignment.BottomCenter
) {
Canvas(modifier, onDraw = {
val centerX = size.width/2
val bottomY = size.height-50
val myColorStops = arrayOf(0.0f to Color.White,1.0f to Color.Black)
//画指针底座
drawCircle(
brush = Brush.radialGradient(colorStops = myColorStops),
radius = 30f,
center = Offset(centerX,bottomY+15.dp.value),
)
drawCircle(
color = Color.White,
radius = 23f,
center = Offset(centerX,bottomY+15.dp.value)
)
drawCircle(
color = Color.Red,
radius = 20f,
center = Offset(centerX,bottomY+15.dp.value)
)
//画单位
drawText(
textMeasurer = mersure,
text = myUnit,
style = TextStyle(color = Color.Black, fontSize = 12.sp, fontWeight = FontWeight(20), fontFamily = FontFamily.Serif),
topLeft = Offset(centerX-50.dp.value,bottomY-90)
)
//画刻度
repeat(61){
val fontWeights = if( it%5==0){
if(it%10==0){
7f
}else{
4f
}
}else{
2f
}
val lengths = if(it%5==0){
if(it%10==0){
25
}else{
22
}
}else{
20
}
drawLine(
color = Color.Black,
start = Offset(
getPointX(centerX,it,bottomY,3),
getPointY(centerX,it,bottomY,3)
),
end = Offset(
getPointX(centerX,it,bottomY-lengths,3),
getPointY(centerX,it,bottomY-lengths,3)
),
strokeWidth = fontWeights,
cap = StrokeCap.Round
)
}
//画数字
repeat(speedTextList.size){
val myTopLeft = Offset(
getPointX(centerX,it,bottomY-70,30)-25.dp.value,
getPointY(bottomY,it,bottomY-70,30))
val colorType = if(it > 4){
Color.Red
}else{
Color.Black
}
drawText(
textMeasurer = mersure,
text = speedTextList[it],
topLeft =myTopLeft,
style = TextStyle(colorType, fontSize = 11.sp, fontFamily = FontFamily.Serif)
)
}
//画指针
drawLine(
color = Color.Red,
start = Offset(
getPointX(centerX,speedNum,bottomY-30,1),
getPointY(centerX,speedNum,bottomY-30,1)
),
end = Offset(
getPointX(centerX,speedNum,0f,1),
getPointY(centerX,speedNum,0f,1)
),
strokeWidth = 15f,
cap = StrokeCap.Round
)
})
}
}
Compose还是蛮香的,用了就回不去了<捂脸>,只是这个代码的可读性没有Java的好。