【问题标题】:Jetpack Compose Draw Arc with Dot CircleJetpack 用点圆组成画弧
【发布时间】:2022-01-04 03:47:28
【问题描述】:

我希望在 Jetpack Compose 的画布上画一条弧线,在进度边缘有一个小圆圈,如下图所示:

我找到了如何使用弧形画布绘制进度条,但还不知道如何绘制圆形以匹配弧线的边缘。这是我的进度代码:

@Composable
fun ComposeCircularProgressBar(
    modifier: Modifier = Modifier,
    percentage: Float,
    fillColor: Color,
    backgroundColor: Color,
    strokeWidth: Dp
) {
    Canvas(
        modifier = modifier
            .padding(strokeWidth / 2)
    ) {
        // Background Line
        drawArc(
            color = backgroundColor,
            135f,
            270f,
            false,
            style = Stroke(strokeWidth.toPx(), cap = StrokeCap.Butt)
        )
        // Fill Line
        drawArc(
            color = fillColor,
            135f,
            270f * percentage,
            false,
            style = Stroke(strokeWidth.toPx(), cap = StrokeCap.Round)
        )
    }
}

注意:目前我知道用Canvas.drawCircle(offset = Offset) 绘制那个圆圈,但我还不知道如何计算Offset(x,y) 以匹配进度的边缘。

【问题讨论】:

  • 这与compose无关,只是一道数学题,例如见this answer

标签: android kotlin android-canvas android-jetpack-compose


【解决方案1】:

下面的这段代码将根据您提供的百分比生成带有圆点的弧线。您确实得到了大部分正确的部分,它只是解决数学方程以找到圆上的点。

我假设圆的半径为小部件的高度/2

由于我们没有绘制完整的圆,因此起始角度为 140 度,最大扫掠角度为 260 度。 (我通过点击和试用找到了这个,所以它看起来和你的图像一样接近)

现在要绘制白色的小圆圈,中心又名 偏移量 必须位于 (x,y) 处,其中 x 和 y 由公式给出

x = 半径 * sin(以弧度表示的角度) y = 半径 * cos(以弧度为单位的角度)

@Composable
fun ComposeCircularProgressBar(
    modifier: Modifier = Modifier,
    percentage: Float,
    fillColor: Color,
    backgroundColor: Color,
    strokeWidth: Dp
) {
    Canvas(
        modifier = modifier
            .size(150.dp)
            .padding(10.dp)
    ) {
        // Background Line
        drawArc(
            color = backgroundColor,
            140f,
            260f,
            false,
            style = Stroke(strokeWidth.toPx(), cap = StrokeCap.Round),
            size = Size(size.width, size.height)
        )

        drawArc(
            color = fillColor,
            140f,
             percentage * 260f,
            false,
            style = Stroke(strokeWidth.toPx(), cap = StrokeCap.Round),
            size = Size(size.width, size.height)
        )


        var angleInDegrees = (percentage * 260.0) + 50.0
        var radius = (size.height / 2)
        var x = -(radius * sin(Math.toRadians(angleInDegrees))).toFloat() + (size.width / 2)
        var y = (radius * cos(Math.toRadians(angleInDegrees))).toFloat() + (size.height / 2)

        drawCircle(
            color = Color.White,
            radius = 5f,
            center = Offset(x,  y)
        )
    }
}

以下是我尝试过的一些示例

@Preview
@Composable
fun PreviewPorgressBar() {
    ComposeCircularProgressBar(
        percentage = 0.80f,
        fillColor = Color(android.graphics.Color.parseColor("#4DB6AC")),
        backgroundColor = Color(android.graphics.Color.parseColor("#90A4AE")),
        strokeWidth = 10.dp
    )
}

@Preview
@Composable
fun PreviewPorgressBar() {
    ComposeCircularProgressBar(
        percentage = 0.45f,
        fillColor = Color(android.graphics.Color.parseColor("#4DB6AC")),
        backgroundColor = Color(android.graphics.Color.parseColor("#90A4AE")),
        strokeWidth = 10.dp
    )
}

@Preview
@Composable
fun PreviewPorgressBar() {
    ComposeCircularProgressBar(
        percentage = 1f,
        fillColor = Color(android.graphics.Color.parseColor("#4DB6AC")),
        backgroundColor = Color(android.graphics.Color.parseColor("#90A4AE")),
        strokeWidth = 10.dp
    )
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-11
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    • 2011-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多