Android Compose:drawArc无法在Box内居中及动态适配问题
解决Compose中drawArc进度条居中及动态适配问题
问题原因分析
- 圆弧居左问题:
drawArc默认从坐标(0,0)开始绘制区域,未指定topLeft偏移量时,圆弧会显示在左上角。 - 尺寸适配问题:直接使用
maxWidth固定比例计算半径和描边,未基于Canvas实际可用尺寸动态调整,导致仅适配单一屏幕。
修复方案及代码
核心思路:基于Canvas自身的尺寸参数动态计算所有绘制值,通过偏移量让圆弧居中,用屏幕最小边的百分比设置描边宽度实现自适应。
Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Canvas( modifier = Modifier .fillMaxSize() .wrapContentSize(Alignment.Center) ) { // 取Canvas最小边作为基准,保证圆为正圆 val minCanvasSize = min(size.width, size.height) // 动态计算描边宽度:基于最小边的百分比,适配不同屏幕 val bgStrokeWidth = minCanvasSize * 0.04f val progressStrokeWidth = minCanvasSize * 0.03f // 圆半径:减去半条描边宽度,避免描边超出Canvas范围 val circleRadius = (minCanvasSize / 2) - (bgStrokeWidth / 2) // 绘制背景圆 drawCircle( color = Color.Gray, radius = circleRadius, style = Stroke(width = bgStrokeWidth, cap = StrokeCap.Round) ) // 计算进度圆弧的绘制区域,确保和背景圆居中对齐 val arcDiameter = circleRadius * 2 val arcTopLeft = Offset( x = (size.width - arcDiameter) / 2, y = (size.height - arcDiameter) / 2 ) val sweepAngle = (progress / 100f) * 360f // 绘制进度圆弧 drawArc( color = Color.Green, topLeft = arcTopLeft, size = Size(arcDiameter, arcDiameter), startAngle = -90f, sweepAngle = sweepAngle, useCenter = false, style = Stroke(width = progressStrokeWidth, cap = StrokeCap.Round) ) } }
关键改动说明
- 移除
BoxWithConstraints,直接使用CanvasScope提供的size参数获取实际绘制区域尺寸,计算更精准。 - 通过
min(size.width, size.height)确保圆始终为正圆,适配横竖屏切换。 - 描边宽度采用屏幕最小边的百分比,平板设备自动加宽描边,小屏设备自动缩小,无需硬编码固定值。
- 计算
arcTopLeft偏移量,让进度圆弧的绘制区域与背景圆完全居中对齐,解决左上角显示问题。
内容的提问来源于stack exchange,提问作者oop
相关产品推荐
相关产品推荐

