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 额外提供:
containerColorindicatorColorcontainerShape
它适合需要独立承载面、或者作为 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。