使用可组合项预览来预览界面

可组合项由函数定义,并使用 @Composable 进行注解:

@Composable
fun SimpleComposable() {
    Text("Hello World")
}

包含“Hello World”字样的简单文本元素

如需实现此可组合项的预览,请再创建一个使用 @Composable 和 @Preview 进行注解的可组合项。这个带有注解的新可组合项现在包含您最初创建的可组合项 SimpleComposable:

@Preview
@Composable
fun SimpleComposablePreview() {
    SimpleComposable()
}

@Preview 注解会告知 Android Studio 此可组合函数应显示在此文件的设计视图中。在您进行修改时,您可以看到可组合项预览的实时更新。

一张显示了使用 Compose 预览进行实时更新的 GIF

您可以在代码中手动添加参数,以自定义 Android Studio 呈现 @Preview 的方式。您甚至可以多次向同一函数添加 @Preview 注解,以预览具有不同属性的可组合项。

使用 @Preview 可组合项的主要好处之一是避免依赖 Android Studio 中的模拟器。您可以将模拟器中占用大量内存的启动过程留给最终的外观和风格更改,并利用 @Preview 轻松进行和测试小幅代码更改。

为了最有效地利用 @Preview 注解,请务必根据屏幕接收的状态(作为输入)和输出的事件来定义屏幕。

设定您的@Preview

Android Studio 提供了一些功能来扩展可组合项预览。您可以更改其容器设计,与之互动,或直接将其部署到模拟器或设备。

维度

默认情况下,系统会自动选择 @Preview 尺寸来封装其内容。如需手动设置尺寸,请添加 heightDp 和 widthDp 参数。这些值已解释为 dp,因此您无需向其添加 .dp:

@Preview(widthDp = 50, heightDp = 50)
@Composable
fun SquareComposablePreview() {
    Box(Modifier.background(Color.Yellow)) {
        Text("Hello World")
    }
}

包含“Hello World”字样的黄色方形

动态配色预览

如果您已在应用中启用动态配色,则可以使用 wallpaper 属性切换壁纸,并在使用不同的用户所选壁纸时查看界面的显示效果。从 Wallpaper 类提供的不同壁纸主题中进行选择。此功能需要 Compose 1.4.0 或更高版本。

在不同设备上使用

在 Android Studio Flamingo 中,您可以修改预览注解的 device 参数,以定义不同设备中可组合项的配置。

可组合函数示例

当设备参数具有空字符串 (@Preview(device = "")) 时,您可以通过按 Ctrl + Space 来调用自动补全功能。然后,您可以设置每个参数的值。

修改示例函数

在自动补全功能中,您可以从列表中选择任何设备选项,例如 @Preview(device = "id:pixel_4")。或者,您也可以选择 spec:width=px,height=px,dpi=int… 来设置每个参数的单独值,从而输入自定义设备。

规范列表

如要应用,请按 Enter;如要取消,请按 Esc。

如果您设置了无效值,声明会带有红色下划线,并且可能会提供修复方法(Alt + Enter [在 macOS 上,则使用 ⌥ + ⏎] > Replace with …)。检查会尝试提供与您的输入最接近的修复方法。

无效值示例

语言区域

如需测试不同的用户语言区域,请添加 locale 参数:

@Preview(locale = "fr-rFR")
@Composable
fun DifferentLocaleComposablePreview() {
    Text(text = stringResource(R.string.greeting))
}

一个简单的文本元素,其中包含“Bonjour”一词和一面法国国旗

设置背景颜色

默认情况下,您的可组合项将以透明背景来显示。如需添加背景,请添加 showBackground 和 backgroundColor 参数。请注意,backgroundColor 是 ARGB Long,而不是 Color 值:

@Preview(showBackground = true, backgroundColor = 0xFF00FF00)
@Composable
fun WithGreenBackground() {
    Text("Hello World")
}

包含“Hello World”字样的绿色矩形

系统界面

如需在预览中显示状态栏和操作栏,请添加 showSystemUi 参数:

@Preview(showSystemUi = true)
@Composable
fun DecoratedComposablePreview() {
    Text("Hello World")
}

一个预览窗口,其中显示了一个具有状态栏和操作栏的 activity。

界面模式

参数 uiMode 可接受任意 Configuration.UI_* 常量,并允许您相应地更改预览的行为。例如,您可以将预览设置为夜间模式,看看主题如何响应。

Compose 预览界面

LocalInspectionMode

您可以通过读取 LocalInspectionMode CompositionLocal 来确认可组合项是否正在预览中呈现(在可检查组件内)。如果可组合项在预览中呈现,LocalInspectionMode.current 的结果为 true。这些信息可让您自定义预览;例如,您可以在预览窗口中显示占位图,而不是显示实际数据。

这样,您还可以避开限制。例如,显示示例数据,而不是调用网络请求。

@Composable
fun GreetingScreen(name: String) {
    if (LocalInspectionMode.current) {
        // Show this text in a preview window:
        Text("Hello preview user!")
    } else {
        // Show this text in the app:
        Text("Hello $name!")
    }
}

与 @Preview 互动

Android Studio 提供的功能可让您与定义的预览进行互动。这种互动有助于您了解预览的运行时行为,并让您能够通过预览更好地浏览界面。

互动模式

借助互动模式,您可以采用类似于在运行程序的设备(例如手机或平板电脑)上互动的方式与预览互动。交互模式被隔离在沙盒环境中(即与其他预览隔离),在该模式下,您可以在预览中点击元素并输入用户输入。通过使用这种模式,您可以快速测试可组合项的不同状态、手势,甚至动画。

用户点击预览的“互动”按钮

用户与预览互动的视频

代码导航和可组合项大纲

您可以将鼠标悬停在预览上,以查看其中包含的可组合项的大纲。点击可组合项大纲会触发您的编辑器视图,从而导航到其定义。

用户将鼠标悬停在预览上,使 Studio 显示其可组合项的大纲

运行预览

您可以在模拟器或实体设备上运行特定 @Preview。预览将作为新的 Activity 部署在同一项目应用中,因此它具有相同的上下文和权限。如果权限已授予,您无需编写样板代码来请求权限。

点击 @Preview 注解旁边或预览顶部的 Run Preview 图标 运行预览
图标,Android Studio 会将该 @Preview 部署到已连接的设备或模拟器上。

用户点击预览的

用户将预览部署到设备的视频

复制 @Preview 呈现

通过右键点击呈现的每个预览,即可将其作为图像来复制。

用户点击预览以将其作为图像来复制。

同一 @Preview 注解的多个预览

您可以展示具有不同规范或传递给可组合项的不同参数的同一 @Preview 可组合项的多个版本。这样,您就可以减少原本需要编写的样板代码。

Multipreview 模板

androidx.compose.ui:ui-tooling-preview 1.6.0-alpha01+ 引入了多预览 API 模板:@PreviewScreenSizes、@PreviewFontScales、@PreviewLightDark 和 @PreviewDynamicColors,这样一来,只需一个注解,您就可以在常见场景中预览 Compose 界面。

使用模板预览不同的字体和屏幕尺寸

创建自定义多预览注解

使用 Multipreview 时,您可以定义一个注解类,该类本身可具有多个采用不同配置的 @Preview 注解。将此注解添加到一个可组合函数后,系统会自动同时呈现所有不同的预览。例如,您可以使用此注解同时预览多个设备、字体大小或主题,而无需为每一个可组合项重复这些定义。

首先,创建您自己的自定义注解类:

@Preview(
    name = "small font",
    group = "font scales",
    fontScale = 0.5f
)
@Preview(
    name = "large font",
    group = "font scales",
    fontScale = 1.5f
)
annotation class FontScalePreviews

您可以对预览可组合项使用此自定义注解:

@FontScalePreviews
@Composable
fun HelloWorldPreview() {
    Text("Hello World")
}

Android Studio 的 Design 标签页,显示了分别采用小号和大号字体的可组合项

您可以将多个 MultiPreview 注解和普通 preview 注解结合使用,从而创建一个更完整的预览集。结合使用 MultiPreview 注解并不意味着所有不同的组合都会得以呈现。实际上,每个 MultiPreview 注解会独立运行,并且仅会呈现自己的变体。

@Preview(
    name = "Spanish",
    group = "locale",
    locale = "es"
)
@FontScalePreviews
annotation class CombinedPreviews

@CombinedPreviews
@Composable
fun HelloWorldPreview2() {
    MaterialTheme { Surface { Text(stringResource(R.string.hello_world)) } }
}

Android Studio 的 Design 标签页,显示了采用所有配置的可组合项

MultiPreview 和普通预览的混搭特性让您可以更全面地测试大型项目的许多属性。

@Preview和大型数据集

很多时候,您需要将大型数据集传递给可组合项预览。为此,您只需使用 @PreviewParameter 注解来添加参数,以将抽样数据传递给某个可组合项预览函数。

@Preview
@Composable
fun UserProfilePreview(
    @PreviewParameter(UserPreviewParameterProvider::class) user: User
) {
    UserProfile(user)
}

如需提供示例数据,请创建一个可实现 PreviewParameterProvider 并以序列形式返回示例数据的类。

class UserPreviewParameterProvider : PreviewParameterProvider<User> {
    override val values = sequenceOf(
        User("Elise"),
        User("Frank"),
        User("Julia")
    )
}

这会为序列中的每个数据元素呈现一个预览:

预览画面中显示 Elise、Frank 和 Julia 可组合项

您可以为多个预览使用相同的提供程序类。如有必要,可通过设置 limit 参数来限制预览数量。

@Preview
@Composable
fun UserProfilePreview2(
    @PreviewParameter(UserPreviewParameterProvider::class, limit = 2) user: User
) {
    UserProfile(user)
}

默认情况下,使用 @PreviewParameter 的预览会使用参数索引和属性名称(用户 0、用户 1、用户 2 等)进行命名,这可能会导致难以区分它们。为了提高预览清晰度,您可以通过在 PreviewParameterProvider 中替换 getDisplayName(),为每个预览提供自定义显示名称。这有助于区分不同的数据变体或界面状态。例如,您可以根据输入数据为预览添加标签:

class UserAgePreviewParameterProvider : PreviewParameterProvider<User> {
    // Using a List internally for efficient index-based access
    private val userList = listOf(
        User(name = "Elise", age = 30),
        User(name = "Frank", age = 31),
        User(name = "Julia", age = 40)
    )

    override val values = userList.asSequence()

    override fun getDisplayName(index: Int): String? {
        // Return null or an empty string to use the default index-based name
        val user = userList.getOrNull(index) ?: return null
        return "${user.name} - ${user.age}"
    }
}

使用自定义显示名称的预览,显示 Elise - 30、Frank - 31 和 Julia - 40 可组合项

AI 辅助预览生成

Android Studio 中的 AI 智能体可以自动为可组合项生成 Compose 预览。右键点击可组合函数,然后选择 AI > 为 [可组合项名称]生成预览。智能体会分析您的可组合项,以生成必要的 @Preview 样板代码和正确的参数,帮助您快速验证界面是否按预期呈现。

使用 AI 生成 Compose 预览。

注解类 @Preview

您可以随时在 Android Studio 中按住 Ctrl 或 ⌘ 键并点击 @Preview 注解,查看自定义预览时可调整的参数的完整列表。

annotation class Preview(
    val name: String = "",
    val group: String = "",
    @IntRange(from = 1) val apiLevel: Int = -1,
    val widthDp: Int = -1,
    val heightDp: Int = -1,
    val locale: String = "",
    @FloatRange(from = 0.01) val fontScale: Float = 1f,
    val showSystemUi: Boolean = false,
    val showBackground: Boolean = false,
    val backgroundColor: Long = 0,
    @UiMode val uiMode: Int = 0,
    @Device val device: String = Devices.DEFAULT,
    @Wallpaper val wallpaper: Int = Wallpapers.NONE,
)

限制和最佳做法

Android Studio 会直接在预览区域中执行预览代码。它不需要运行模拟器或实体设备,因为它利用了 Android 框架的移植部分,称为 Layoutlib。Layoutlib 是 Android 框架的自定义版本,旨在在 Android 设备之外运行。该库的目标是在 Android Studio 中提供与设备上的渲染效果非常接近的布局预览。

预览限制

由于预览在 Android Studio 中的呈现方式,它们是轻量级的,不需要整个 Android 框架来呈现它们。不过,这会带来以下限制:

  • 无法访问网络
  • 无法访问文件
  • 有些 Context API 不一定完全可用

预览和ViewModels

在可组合项中使用 ViewModel 时,预览功能会受到限制。预览系统无法构建传递给 ViewModel 的所有参数,例如代码库、用例、管理器或类似参数。此外,如果您的 ViewModel 参与依赖项注入(例如使用 Hilt),预览系统将无法构建整个依赖项图表来构造 ViewModel。

当您尝试预览带有 ViewModel 的可组合项时,Android Studio 会在渲染特定可组合项时显示错误:

Android Studio 问题窗格,其中显示“Failed to instantiate a `ViewModel`”消息

如果您想预览使用 ViewModel 的可组合项,应创建另一个可组合项,并将 ViewModel 中的参数作为该可组合项的实参传递。这样一来,您就无需预览使用 ViewModel 的可组合项。

@Composable
fun AuthorScreen(viewModel: AuthorViewModel = viewModel()) {
  AuthorScreen(
    name = viewModel.authorName,
    // ViewModel sends the network requests and makes posts available as a state
    posts = viewModel.posts
  )
}

@Composable
fun AuthorScreen(
  name: NameLabel,
  posts: PostsList
) {
  // ...
}

@Preview
@Composable
fun AuthorScreenPreview(
  // You can use some sample data to preview your composable without the need to construct the ViewModel
  name: String = sampleAuthor.name,
  posts: List<Post> = samplePosts[sampleAuthor]
) {
  AuthorScreen(
      name = NameLabel(name),
      posts = PostsList(posts)
  )
}

其他资源

  • 如需详细了解 Android Studio 如何提升 @Preview 的易用性,以及了解更多工具提示,请参阅 Compose 工具博文。
  • 如需查看旧版 View 指南,请参阅使用 View 开发布局。