LoadingIndicator:进度驱动形状变化 · AndroidX 源码指南
AAndroidX 源码指南
M3E 设计系统
ANDROIDX / COMPOSE / MATERIAL 3

LoadingIndicator:进度驱动形状变化

区分确定与不确定进度、普通与 contained 版本,并正确传递 progress 和 polygon 序列。

四种组合

LoadingIndicator 有两个维度:

无容器有色容器
不确定进度LoadingIndicator()ContainedLoadingIndicator()
确定进度LoadingIndicator(progress = { value })ContainedLoadingIndicator(progress = { value })

这四个 public overload 都标记了 ExperimentalMaterial3ExpressiveApi

不确定进度

当你不知道任务完成比例,只知道它仍在工作:

@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
fun Loading() {
    LoadingIndicator()
}

只要组件保持可见,它就会在默认的多个 polygon 之间持续 morph。

确定进度

var progress by remember { mutableFloatStateOf(0f) }

LoadingIndicator(progress = { progress })

注意参数类型是 () -> Float,不是直接传 Float。源码把范围外数值约束到 0f..1f,并按进度在 polygon 序列之间插值。

AndroidX sample 先用 animateFloatAsState 平滑 progress,再交给 LoadingIndicator;这样业务进度跳变时,形状不会瞬间跨越多个阶段。

Contained 版本什么时候用

ContainedLoadingIndicator 额外提供:

  • containerColor
  • indicatorColor
  • containerShape

它适合需要独立承载面、或者作为 Pull to Refresh 指示器的场景。普通版本更适合已经有明确背景的内容区域。

自定义 polygon 的硬约束

两种版本都允许传入 List<RoundedPolygon>。源码要求列表至少包含两个元素,否则抛出 IllegalArgumentException。这不是装饰性建议,而是 morph 建立起点和终点所需的最低条件。

LoadingIndicator(
    polygons = listOf(firstPolygon, secondPolygon),
)

第一步建议先使用 LoadingIndicatorDefaults,确认尺寸、颜色和场景正确后再自定义形状序列。

复制即用

不确定与确定进度的四种组合:

import androidx.compose.material3.ContainedLoadingIndicator
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.LoadingIndicator
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue

@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
fun Indeterminate() {
    LoadingIndicator() // 不知道进度时
}

@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
fun Determinate() {
    var progress by remember { mutableFloatStateOf(0.5f) }

    LoadingIndicator(progress = { progress })
}

@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
fun ContainedIndeterminate() {
    ContainedLoadingIndicator() // 带容器
}

@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
fun ContainedDeterminate() {
    var progress by remember { mutableFloatStateOf(0.5f) }

    ContainedLoadingIndicator(progress = { progress })
}

自定义 polygon 序列必须至少两个元素,否则抛 IllegalArgumentException