针对不同屏幕尺寸开发

您的应用应在所有尺寸的 Wear OS 设备上都能正常运行,在可用时利用额外的空间,并且在较小的屏幕上也能保持良好的外观。本指南提供了实现此用户体验的建议。

要详细了解自适应布局的设计原则,请阅读 设计指南

使用 Horologist 构建响应式布局

布局应具有 基于百分比的边距。由于 Compose 默认情况下使用绝对值,因此请使用来自 Horologist 库 的组件,该库具有以下功能

  • 水平边距根据设备屏幕尺寸的百分比正确设置。

  • 顶部和底部间距已正确设置。这带来了特殊的挑战,因为推荐的顶部和底部间距可能取决于所使用的组件。例如,在列表中使用Chip时,其间距应与Text组件不同。
  • TimeText的边距已正确设置。

以下代码片段使用 Horologist 版本的ScalingLazyColumn 布局来创建在各种 Wear OS 屏幕尺寸上看起来都很棒的内容

val columnState = rememberResponsiveColumnState(
    contentPadding = ScalingLazyColumnDefaults.padding(
        first = ScalingLazyColumnDefaults.ItemType.Text,
        last = ScalingLazyColumnDefaults.ItemType.SingleButton
    )
)
ScreenScaffold(scrollState = columnState) {
    ScalingLazyColumn(
        columnState = columnState
    ) {
        item {
            ResponsiveListHeader(contentPadding = firstItemPadding()) {
                Text(text = "Header")
            }
        }
        // ... other items
        item {
            Button(
                imageVector = Icons.Default.Build,
                contentDescription = "Example Button",
                onClick = { }
            )
        }
    }
}

此示例还演示了ScreenScaffoldAppScaffold。这些组件协调应用程序和各个屏幕(导航路线)之间的关系,以确保正确的滚动行为和TimeText定位。

对于顶部和底部填充,还要注意以下几点

  • 第一个和最后一个ItemType的规范,以确定正确的填充。
  • 使用ResponsiveListHeader 作为列表中的第一个项目,因为Text标题不应该有填充。

完整规范可以在Figma 设计套件中找到。有关更多详细信息和示例,请参阅

  • The Horologist 库 - 提供组件来帮助构建针对 Wear OS 的优化和差异化应用程序。
  • The ComposeStarter 示例 - 展示本指南中概述的原则的示例。
  • The JetCaster 示例 - 一个更复杂的构建应用程序以适应不同屏幕尺寸的示例,使用 Horologist 库。

在你的应用中使用滚动布局

在实现屏幕时,将滚动布局(如本页前面所示)作为默认选择。这使用户无论显示偏好或 Wear OS 设备屏幕尺寸如何,都能访问应用程序的组件。

The effect of different device size and font-scaling

不同设备尺寸和字体缩放的效果。

对话框

对话框也应该可以滚动,除非有充分的理由不滚动。Horologist 提供的ResponsiveDialog 组件添加了以下功能

  • 默认情况下可滚动。
  • 正确的基于百分比的边距。
  • 按钮在有空间时调整其宽度,以提供更大的点击目标。
Adaptive dialog behavior in Horologist

自适应对话框,默认提供滚动功能,并且按钮可以适应可用空间。

自定义屏幕可能需要非滚动布局

某些屏幕可能仍然适合使用非滚动布局。一些示例包括媒体应用程序中的主要播放器屏幕和健身应用程序中的锻炼屏幕。

在这些情况下,请查看Figma 设计套件中提供的规范指南,并使用正确的边距实现一个对屏幕尺寸做出响应的设计。

通过断点提供差异化的体验

对于较大的显示屏,您可以引入更多内容和功能。要实现这种差异化体验,请使用“屏幕尺寸断点”,当屏幕尺寸超过 225 dp 时显示不同的布局

const val LARGE_DISPLAY_BREAKPOINT = 225

@Composable
fun isLargeDisplay() =
    LocalConfiguration.current.screenWidthDp >= LARGE_DISPLAY_BREAKPOINT

// ...
// ... use in your Composables:
    if (isLargeDisplay()) {
        // Show additional content.
    } else {
        // Show content only for smaller displays.
    }
    // ...

The 设计指南 演示了更多此类机会。

使用预览测试屏幕和字体尺寸的组合

Compose 预览 可帮助您为各种 Wear OS 屏幕尺寸开发应用。使用设备和字体缩放预览定义来查看以下内容

  • 屏幕在尺寸极端情况下的显示效果,例如,最大字体配以最小屏幕。
  • 差异化体验在断点上的行为。

确保你使用WearPreviewDevicesWearPreviewFontScales 为应用程序中的所有屏幕实现预览。

@WearPreviewDevices
@WearPreviewFontScales
@Composable
fun ComposeListPreview() {
    ComposeList()
}

屏幕截图测试

除了预览测试之外,屏幕截图测试还允许您针对一系列现有的硬件尺寸进行测试。这在您可能无法立即获得这些设备,并且问题可能不会出现在其他屏幕尺寸上的情况下特别有用。

屏幕截图测试还有助于您识别代码库中特定位置的回归。

我们的示例使用Roborazzi 进行屏幕截图测试

  1. 配置你的项目应用 build.gradle 文件以使用 Roborazzi。
  2. 为应用程序中的每个屏幕创建一个屏幕截图测试。例如,在 ComposeStarter 示例中,GreetingScreen 的测试如GreetingScreenTest 中所示。
@RunWith(ParameterizedRobolectricTestRunner::class)
class GreetingScreenTest(override val device: WearDevice) : WearScreenshotTest() {
    override val tolerance = 0.02f

    @Test
    fun greetingScreenTest() = runTest {
        AppScaffold(
            timeText = { ResponsiveTimeText(timeSource = FixedTimeSource) }
        ) {
            GreetingScreen(greetingName = "screenshot", onShowList = {})
        }
    }

    companion object {
        @JvmStatic
        @ParameterizedRobolectricTestRunner.Parameters
        fun devices() = WearDevice.entries
    }
}

一些需要注意的重要事项

  • FixedTimeSource 允许您生成TimeText 不变的屏幕截图,从而避免意外导致测试失败。
  • WearDevice.entries 包含大多数流行的 Wear OS 设备的定义,以便在各种屏幕尺寸上运行测试。

生成黄金图像

要为屏幕生成图像,请在终端中运行以下命令

./gradlew recordRoborazziDebug

验证图像

要针对现有图像验证更改,请在终端中运行以下命令

./gradlew verifyRoborazziDebug

有关屏幕截图测试的完整示例,请参阅ComposeStarter 示例。