Jetpack Compose 中的循环加载圆形进度条

7

我想在Jetpack Compose中创建加载动画。我没有视频,但是我有一张图片展示它的样子。

enter image description here

我只知道CircularProgressIndicator,但我不知道如何自定义使其看起来像上面的图片。

    CircularProgressIndicator(
            progress = progress,
            color = progressColor,
            strokeWidth = strokeWidth,
            modifier = Modifier.fillMaxSize()
    )

提前致谢。

更新

我找到了一个视频,它看起来像Twitter在Web上的加载动画。我制作了一个小视频截图,请在Youtube上查看。

2个回答

12

你好!请尝试这个并回答我。

@Composable
fun Indicator(
    size: Dp = 32.dp, // indicator size
    sweepAngle: Float = 90f, // angle (lenght) of indicator arc
    color: Color = MaterialTheme.colors.primary, // color of indicator arc line
    strokeWidth: Dp = ProgressIndicatorDefaults.StrokeWidth //width of cicle and ar lines
) {
    ////// animation //////

    // docs recomend use transition animation for infinite loops
    // https://developer.android.com/jetpack/compose/animation
    val transition = rememberInfiniteTransition()

    // define the changing value from 0 to 360.
    // This is the angle of the beginning of indicator arc
    // this value will change over time from 0 to 360 and repeat indefinitely.
    // it changes starting position of the indicator arc and the animation is obtained
    val currentArcStartAngle by transition.animateValue(
        0,
        360,
        Int.VectorConverter,
        infiniteRepeatable(
            animation = tween(
                durationMillis = 1100,
                easing = LinearEasing
            )
        )
    )

    ////// draw /////

    // define stroke with given width and arc ends type considering device DPI
    val stroke = with(LocalDensity.current) {
        Stroke(width = strokeWidth.toPx(), cap = StrokeCap.Square)
    }

    // draw on canvas
    Canvas(
        Modifier
            .progressSemantics() // (optional) for Accessibility services
            .size(size) // canvas size
            .padding(strokeWidth / 2) //padding. otherwise, not the whole circle will fit in the canvas
    ) {
        // draw "background" (gray) circle with defined stroke.
        // without explicit center and radius it fit canvas bounds
        drawCircle(Color.LightGray, style = stroke)

        // draw arc with the same stroke
        drawArc(
            color,
            // arc start angle
            // -90 shifts the start position towards the y-axis
            startAngle = currentArcStartAngle.toFloat() - 90,
            sweepAngle = sweepAngle,
            useCenter = false,
            style = stroke
        )
    }
}

简而言之,在画布上绘制一个圆,然后在其上方绘制指示器弧。
可传递的动画将“currentArcStartAngle”变量的值从0循环到360(这是圆中的角度),并使用此变量来设置指示器弧的起始角度。
为了更好地理解起始角度,请在“drawArc”中使用“useCenter = true”。
“currentArcStartAngle”是状态,因此每次更改都会导致重新组合画布并以新的起始角度重新绘制。
结果: enter image description here

你能详细解释一下你在做什么吗? - Kotlin Learner
@vivekmodi 完成。我添加了注释和描述。 - vitidev

7

你可以使用Modifier.drawBehind在进度条后面绘制另一个圆形。

val strokeWidth = 5.dp

CircularProgressIndicator(
    modifier = Modifier.drawBehind {
        drawCircle(
            Color.Red,
            radius = size.width / 2 - strokeWidth.toPx() / 2,
            style = Stroke(strokeWidth.toPx())
        )
    },
    color = Color.LightGray,
    strokeWidth = strokeWidth
)

如何设置宽度和高度为 17 x 16 - Kotlin Learner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接