在 Wear OS 设备上,列表用于提供一组选项来供用户选择。
许多 Wear OS 设备都使用圆形屏幕,用户不方便查看靠近屏幕顶部和底部的列表项。因此,Compose for Wear OS 提供了一个名为 TransformingLazyColumn 的 LazyColumn 类版本,该版本支持缩放和形变动画。当有列表项移至屏幕边缘时,便会缩小并淡出。
如需应用建议的缩放和滚动效果,请执行以下操作:
- 使用
Modifier.transformedHeight,让 Compose 计算列表项在屏幕上滚动时的高度变化。 - 使用
transformation = SurfaceTransformation(transformationSpec)应用视觉效果,包括缩小列表项内容。 - 对于不使用
transformation作为参数的组件(例如Text),请使用自定义TransformationSpec。
以下动画演示了列表元素在接近屏幕顶部和底部时如何缩放和改变形状:
以下代码段展示了如何使用TransformingLazyColumn 布局创建可在各种 Wear OS 屏幕尺寸上呈现出色效果的内容。
此代码段还演示了 minimumVerticalContentPadding 修饰符的用法,您应在列表项上设置该修饰符,以便在列表顶部和底部应用正确的内边距。
如需显示滚动指示器,请在 ScreenScaffold 和 TransformingLazyColumn 之间共享 columnState:
val columnState = rememberTransformingLazyColumnState() val transformationSpec = rememberTransformationSpec() ScreenScaffold( scrollState = columnState ) { contentPadding -> TransformingLazyColumn( state = columnState, contentPadding = contentPadding ) { item { ListHeader( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding), transformation = SurfaceTransformation(transformationSpec) ) { Text(text = "Header") } } // ... other items item { Button( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding), transformation = SurfaceTransformation(transformationSpec), onClick = { /* ... */ }, icon = { Icon( imageVector = Icons.Default.Build, contentDescription = "build", ) }, ) { Text( text = "Build", maxLines = 1, overflow = TextOverflow.Ellipsis, ) } } } }
添加贴靠和快速滑动效果
贴靠可确保当用户完成滚动或轻拂手势时,列表会停在某个项精确位于特定点(通常是屏幕中心)的位置。在圆形屏幕上,当项目远离中心时,会进行缩放和变形,因此贴靠功能非常有用,可确保最相关的项目在最佳观看区域内保持完全可见和可读。如需添加贴靠和轻拂行为,请将 flingBehavior 参数设置为 TransformingLazyColumnDefaults.snapFlingBehavior(columnState)。将 rotaryScrollableBehavior 设置为匹配,使用 RotaryScrollableDefaults.snapBehavior(columnState) 可在实体表冠或表圈上获得一致的体验。
val columnState = rememberTransformingLazyColumnState() ScreenScaffold(scrollState = columnState) { contentPadding -> TransformingLazyColumn( state = columnState, flingBehavior = TransformingLazyColumnDefaults.snapFlingBehavior(columnState), rotaryScrollableBehavior = RotaryScrollableDefaults.snapBehavior(columnState) ) { // ... // ... } }
反向布局
默认情况下,可滚动列表会锚定到其顶部边缘。如果用户已滚动到标准列表的底部,并且在末尾添加了新项,则列表会保持用户对当前项的视图。例如,如果用户正在查看屏幕底部的商品 10,并且添加了商品 11,则视图仍会聚焦于商品 10,而商品 11 会显示在当前视图下方的屏幕外。
对于消息传递应用或实时日志等使用情形,通常不希望出现此行为。当新内容到达时,如果用户已位于列表底部,通常会希望立即看到最新内容。如果一次到达多个商品,列表应跳过,在底部显示最新商品(这意味着除非用户向上滚动,否则可能根本不会显示某些中间商品)。
为了支持这些使用情形,TransformingLazyColumn 可让您通过设置 reverseLayout = true 来反转布局。这样会将列表的锚点从顶部边缘更改为底部边缘。
为方便起见,设置 reverseLayout = true 还会反转商品的视觉顺序和滚动手势的方向:
- 项目从底部到顶部组成,这意味着索引 0 显示在屏幕底部。
- 向上滚动可显示索引值较高的项。
如需添加贴靠和轻拂行为以及反向布局,您可以结合使用 flingBehavior 和 rotaryScrollableBehavior,如以下代码段所示:
val columnState = rememberTransformingLazyColumnState() val transformationSpec = rememberTransformationSpec() ScreenScaffold(scrollState = columnState) { contentPadding -> TransformingLazyColumn( state = columnState, contentPadding = contentPadding, reverseLayout = true, modifier = Modifier.fillMaxWidth() ) { items(10) { index -> Button( label = { Text( text = "Item ${index + 1}" ) }, onClick = {}, modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding), transformation = SurfaceTransformation(transformationSpec) ) } item { // With reverseLayout = true, the last item declared appears at the top. ListHeader( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding), transformation = SurfaceTransformation(transformationSpec) ) { Text("Header") } } } }
以下图片展示了普通列表与反向列表之间的区别:
列表中的边缘按钮
对于 Material 3,您可以添加 EdgeButton,这是一个位于列表底部的贴边按钮。不过,请注意不要将其添加为 TransformingLazyColumn 中的项,而应使用 ScreenScaffold 中的 edgeButton slot。
使用 edgeButton slot 可确保按钮正确放置在屏幕底部,并在列表滚动时正常运行。
以下代码段展示了如何实现 EdgeButton:
val columnState = rememberTransformingLazyColumnState() ScreenScaffold( scrollState = columnState, edgeButton = { EdgeButton( onClick = { /* TODO */ }, modifier = Modifier.scrollable( columnState, orientation = Orientation.Vertical, reverseDirection = true, // Apply overscroll to the EdgeButton for proper scrolling behavior. overscrollEffect = rememberOverscrollEffect(), ) ) { Text("More") } } ) { contentPadding -> TransformingLazyColumn( contentPadding = contentPadding, state = columnState, ) { // ... // ... } }
在列表中滑动以显示
借助 SwipeToReveal 组件,您可以通过滑动来访问列表项的操作,例如 Card 或 Chip。滑动通常会从侧面显示一个或两个操作按钮(例如“删除”或“更多”)。
在 TransformingLazyColumn 中使用 SwipeToReveal 时,请遵循以下准则:
- 在滚动时重置:当用户滚动列表时,将所有已滑动打开的项重置为覆盖状态。
- 高度一致:将操作按钮的高度设置为与内部滑动项(无论是
Button还是Card)的高度一致,以确保外观一致。 - 转换容器:将
transformedHeight修饰符和transformationSpec应用于SwipeToReveal组件本身。 - 请勿进行双重转换:请勿对内部滑动项(
SwipeToReveal容器内的卡片或按钮)应用transformedHeight或transformation修饰符。
为你推荐
- 注意:当 JavaScript 处于关闭状态时,系统会显示链接文字
- Compose for Wear OS Codelab
- 列表和网格
- 在 Compose 中使用 View