Jetpack Compose 自定义进度条弹窗

668 阅读2分钟

「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战

圆形的进度条

自定义弹窗之前我们继续上一篇文章,接着再自定义一个圆形的进度条

我们利用Canvas里面的drawArc方法画一个圆

我们要动态计算圆的框高 首先获取画布的宽高

Canvas {
    val canvasWidth = size.width  // 画布的宽
    val canvasHeight = size.height  // 画布的高
 
}

为了美观要加入Stroke所以要减去stroke的宽度才等于外圆的宽

val strokeWidth = canvasWidth / 10
val strokeHeight = canvasHeight / 10
//外圆宽
val outerWidth = canvasWidth - strokeWidth
val outerHeight = canvasHeight - strokeHeight

画一个圆

drawArc(
    color = Color.Cyan,
    startAngle = 0F,
    sweepAngle = 360F),
    useCenter = false,
    style = Stroke(
        width = strokeWidth,
        cap = StrokeCap.Round
    ),
    size = Size(outerWidth, outerHeight),
)

3e81298c2e545d8ff8119b86287faa0.jpg

startAngle : 以度为单位的起始角。0代表3点钟

sweepAngle : 相对于startAngle顺时针绘制的弧的大小(以度为单位)

那么当前进度就等于 360度*value的比值

接着中间放入一个进度文本

@Composable
private fun progressbar(modifier: Modifier = Modifier, value: Float) {
    Box(
        contentAlignment = Alignment.Center
    ) {
        Canvas(modifier.height(166.dp).width(166.dp)) {

            val canvasWidth = size.width  // 画布的宽
            val canvasHeight = size.height  // 画布的高
            val strokeWidth = canvasWidth / 10
            val strokeHeight = canvasHeight / 10
            //外圆宽
            val outerWidth = canvasWidth - strokeWidth
            val outerHeight = canvasHeight - strokeHeight

            drawArc(
                color = Color.Cyan,
                startAngle = -90F,
                sweepAngle = 360*(value/100),
                useCenter = false,
                style = Stroke(
                    width = strokeWidth,
                    cap = StrokeCap.Round
                ),
                size = Size(outerWidth, outerHeight),
            )
        }

            Text(text="${value.toInt()}%  ", color = Color.White)

    }

}

70816828418538cfa35d811a4d2ecad.jpg

简单的Dialog

val dialogWidth = 600.dp
val dialogHeight = 200.dp
val openDialog = remember { mutableStateOf(true) }

    Dialog(onDismissRequest = { openDialog.value = false }) {
        Box(
            Modifier.size(dialogWidth, dialogHeight),           
        ) {
          
        }
    }

接着把进度条放到里面

@Composable
private fun ProgressbarDialog(open:Boolean,value: Float) {
    val dialogWidth = 600.dp
    val dialogHeight = 200.dp
    val openDialog = remember { mutableStateOf(true) }
    openDialog.value = open
    if (openDialog.value) {
        Dialog(onDismissRequest = { openDialog.value = false }) {
            Box(
                Modifier
                    .background(Color.White)
                    .size(dialogWidth, dialogHeight),
                contentAlignment = Alignment.Center
            ) {
                progressbar(value = value)
            }
        }
    }

}

用个按钮模拟启动网络请求

val open = remember { mutableStateOf(false) }
var progressValue by remember { mutableStateOf(0F) }

if (open.value)
LaunchedEffect(rememberScaffoldState()) {
    for (i in 0..100) {
        delay(30)
        progressValue = i.toFloat()
        if(i==100){
        //关闭弹窗
            open.value = false
        }

    }
}
ProgressbarDialog(open = open.value,value = progressValue)

Button(
    onClick = {
        open.value = true
    },
) {
    Text(
        text = "进度条弹窗"
    )
}

圆形效果 video_220201_225933.gif

线形效果

video_220201_230027.gif