Compose学习之绘制速度表盘

内心想法XX

compose已经发布好久了,还没有用过compose写过UI,之前只是在官网上了解过,看着这可组合函数嵌套,我就脑袋大,更Flutter一个德行,我的内心是抵触的,还是觉得用XML写香,抱着试一试的心态,打算用compose应用于实际项目中。(还是得多接触,多学习,真的是很香YYDS)

无图无真相

上图,测试:通过滑动slider也是安卓称ProgressBar来改变速度
Compose学习之绘制速度表盘_第1张图片

代码部分

@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的好。

你可能感兴趣的:(Compose,kotlin,android,jetpack,Compose)