针对不同屏幕尺寸开发

您的应用应该在所有尺寸的 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 library - 提供组件来帮助构建针对 Wear OS 的优化和差异化应用。
  • The ComposeStarter sample - 展示了本指南中概述的原则的示例。
  • The JetCaster sample - 使用 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.
    }
    // ...

设计指南 说明了更多此类机会。

使用预览测试屏幕和字体大小的组合

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 示例。