Material 3 进度组件识别:LinearProgressIndicator、CircularProgressIndicator 的 Compose API

在 UI 自动化测试中,准确识别待测进度组件是编写可靠断言的前提。Material 3 提供了两种互补的进度指示器:LinearProgressIndicator(线性)和 CircularProgressIndicator(圆形)。本章从测试视角梳理两者的 Compose API 核心参数、构造方式与可观察属性,为后续在测试代码中通过 Semantics 树定位进度元素奠定基础。

测试前提: 确保项目已引入 Material 3 依赖。在 build.gradle.kts (模块级) 中添加:
dependencies {
    implementation("androidx.compose.material3:material3:1.2.0")
    androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.6.0")
}

2.1 核心 API 对比

参数 / 特性LinearProgressIndicatorCircularProgressIndicator
形状水平长条圆形轨迹
方向水平 (可设置 track 宽度)无方向性 (旋转动画)
进度范围0f .. 1f (确定模式) / null (不确定模式)0f .. 1f (确定模式) / null (不确定模式)
关键参数progress, trackColor, indicatorColor, strokeWidthprogress, trackColor, indicatorColor, strokeWidth
Semantics 角色ProgressBarProgressBar
无障碍值自动映射 progress 为 rangeValue自动映射 progress 为 rangeValue
测试 Tag 注入Modifier.testTag("myLinear")Modifier.testTag("myCircular")

2.2 LinearProgressIndicator API 详解

线性进度条通常用于页面顶部或卡片内,展现连续任务的整体进度。构造函数签名如下(省略装饰参数):

@Composable
fun LinearProgressIndicator(
    progress: Float?,           // null → 不确定模式; 0f..1f → 确定模式
    modifier: Modifier = Modifier,
    color: Color = MaterialTheme.colorScheme.primary,
    trackColor: Color = MaterialTheme.colorScheme.surfaceVariant,
    strokeWidth: Dp = ProgressIndicatorDefaults.StrokeWidth,
    ... // 其他 Material 3 特定参数
)
  • 确定模式示例:progress = 0.5f → 填充 50%
  • 不确定模式示例:progress = null → 持续滚动动画(未显示具体百分比)
  • 测试定位:通过 onNodeWithTag("linearProgress") 或 onNode(hasProgressBarRole()) 获取
测试代码片段(确定模式):
@get:Rule
val composeTestRule = createComposeRule()

// 在 Compose 中设置
composeTestRule.setContent {
    val progress by remember { mutableStateOf(0.3f) }
    LinearProgressIndicator(
        progress = progress,
        modifier = Modifier.testTag("downloadProgress")
    )
}

// 断言
composeTestRule
    .onNodeWithTag("downloadProgress")
    .assertExists()
    .assertSemanticsMatcher("progressValue") {
        it.getFloat(SemanticsProperties.ProgressBarRangeInfo)?.current ?: 0f
    }

2.3 CircularProgressIndicator API 详解

圆形进度条常用于加载转圈、文件上传等场景。API 结构与线性版本高度一致:

@Composable
fun CircularProgressIndicator(
    progress: Float?,
    modifier: Modifier = Modifier,
    color: Color = MaterialTheme.colorScheme.primary,
    trackColor: Color = MaterialTheme.colorScheme.surfaceVariant,
    strokeWidth: Dp = ProgressIndicatorDefaults.StrokeWidth,
    ... // 大小、间隙等参数
)
  • 确定模式:progress = 0.75f → 圆弧角度为 270°
  • 不确定模式:progress = null → 圆环连续旋转
  • 测试中区分:可通过 onNodeWithTag("circularProgress") 定位;两种指示器 Semantics 角色均为 ProgressBar,需用 Tag 或额外属性区分
常见错误: 将 progress 传入 Float.NaN 或超出 [0,1] 范围会导致异常。始终确保在确定模式下 progress 的值在 0f..1f 之间。
// ❌ 错误:进度值越界
CircularProgressIndicator(progress = 1.5f) // 运行时崩溃
// ✅ 正确:使用 clamp 或业务逻辑约束
CircularProgressIndicator(progress = currentValue.coerceIn(0f, 1f))

2.4 通过 Semantics 树识别进度组件

测试框架通过 Composable 的 Semantics 属性感知进度指示器。两个组件自动附加以下关键属性:

属性含义测试 API
Role.ProgressBar标识为进度条角色hasProgressBarRole()
ProgressBarRangeInfo包含 current (当前值) 和 range (范围)assert(ProgressBarRangeInfo)
TestTag通过 Modifier.testTag 注入的唯一标识onNodeWithTag("tag")
ContentDescription无障碍描述(可选)onNodeWithContentDescription("加载中")
调试技巧: 在测试中使用 composeTestRule.onRoot().printToLog("PROGRESS") 打印完整 Semantics 树,查看进度指示器的真实属性值。

2.5 性能与稳定性优化提示

  • 避免在 Compose 中频繁触发 recomposition: 进度值更新应使用 derivedStateOf 或 snapshotFlow 过滤高频变化,防止测试中超时。
  • 测试中等待进度: 使用 composeTestRule.waitForIdle() 或 waitUntil 等待进度值稳定。
  • 异步更新进度: 协程中的进度更新应挂起于 Dispatchers.Main,测试时可通过 runTest + advanceUntilIdle() 控制时间。
Material 3 进度组件 API 关系图 State 层 progress: Float? Modifier.testTag() Composable 层 LinearProgressIndicator CircularProgressIndicator 测试断言点 hasProgressBarRole() assertSemanticsMatcher 💡 测试要点: • 优先使用 testTag 区分同屏多个进度指示器 • 确定模式下通过 ProgressBarRangeInfo.current 获取百分比值
关键总结: 两个组件在 Semantics 树中共享 ProgressBar 角色,通过 Modifier.testTag() 和 progress 值可唯一识别。测试时注意不确定模式(progress=null)下 ProgressBarRangeInfo 的 current 为 null,应单独判断。