进度指示器

进度指示器以直观的方式显示操作的状态。它们通过动画效果让用户注意到流程(例如加载或处理数据)即将完成。它们还可以表示正在进行处理,而无需参考处理进度。

请考虑以下三种可能需要使用进度指示器的应用场景:

  • 加载内容:从网络提取内容时,例如加载图片或用户个人资料的数据。
  • 文件上传:向用户反馈上传可能需要多长时间。
  • 长时间处理:当应用正在处理大量数据时,向用户传达已完成的总量。

在 Material Design 中,进度指示器分为两种类型:

  • 确定:确切显示已完成的进度。
  • 不确定:持续播放动画,不考虑进度。

同样,进度指示器可以采用以下两种形式之一:

  • 线性:从左到右填充的水平条。
  • 圆形:一个圆圈,其描边长度会不断增加,直到覆盖整个圆周。
线性进度指示器和环形进度指示器。
图 1. 两种类型的进度指示器。

API Surface

虽然您可以使用多个可组合项来创建符合 Material Design 规范的进度指示器,但它们的参数并无太大差异。您应注意的关键参数包括:

  • progress:指示器显示的当前进度。传递介于 0.0 和 1.0 之间的 Float。
  • color:实际指示器的颜色。也就是说,该部分反映了进度,并在进度完成时完全覆盖组件。
  • trackColor:绘制指示器的轨道的颜色。

确定性指示器

确定性指示器可准确反映操作的完成程度。请使用 LinearProgressIndicator 或 CircularProgressIndicator 可组合项,并为 progress 参数传递一个值。

以下代码段提供了一个相对详细的示例。当用户按下按钮时,应用会显示进度指示器,并启动一个协程来逐渐增加 progress 的值。这会导致进度指示器依次向上迭代。

@Composable
fun LinearDeterminateIndicator() {
    var currentProgress by remember { mutableFloatStateOf(0f) }
    var loading by remember { mutableStateOf(false) }
    val scope = rememberCoroutineScope() // Create a coroutine scope

    Column(
        verticalArrangement = Arrangement.spacedBy(12.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier.fillMaxWidth()
    ) {
        Button(onClick = {
            loading = true
            scope.launch {
                loadProgress { progress ->
                    currentProgress = progress
                }
                loading = false // Reset loading when the coroutine finishes
            }
        }, enabled = !loading) {
            Text("Start loading")
        }

        if (loading) {
            LinearProgressIndicator(
                progress = { currentProgress },
                modifier = Modifier.fillMaxWidth(),
            )
        }
    }
}

/** Iterate the progress value */
suspend fun loadProgress(updateProgress: (Float) -> Unit) {
    for (i in 1..100) {
        updateProgress(i.toFloat() / 100)
        delay(100)
    }
}

当加载部分完成时,上述示例中的线性指示器如下所示:

同样,圆形指示器如下所示:

不确定进度指示器

不确定指示器不会反映操作距离完成还有多远。相反,它会使用动画向用户指示处理正在进行中,但不会指定任何完成程度。

如需创建不确定进度指示器,请使用 LinearProgressIndicator 或 CircularProgressIndicator 可组合项,但不要为 progress 传入值。以下示例演示了如何通过按下按钮来切换不确定指示器。

@Composable
fun IndeterminateCircularIndicator() {
    var loading by remember { mutableStateOf(false) }

    Button(onClick = { loading = true }, enabled = !loading) {
        Text("Start loading")
    }

    if (!loading) return

    CircularProgressIndicator(
        modifier = Modifier.width(64.dp),
        color = MaterialTheme.colorScheme.secondary,
        trackColor = MaterialTheme.colorScheme.surfaceVariant,
    )
}

以下是该指示器处于活动状态时的实现示例:

以下是相同实现的示例,但使用的是 LinearProgressIndicator 而不是 CircularProgressIndicator。

其他资源