产品资讯

Jetpack Compose 2026 年 4 月版的最新动态

阅读用时:5 分钟
Meghan Mehta
开发技术推广工程师,Android

今天,Jetpack Compose 2026 年 4 月版已稳定。此版本包含核心 Compose 模块的 1.11 版(请参阅完整的 BOM 映射)、共享元素调试工具、触控板事件等。我们还有一些实验性 API,希望您能试用一下并向我们提供反馈。

如需使用今天的版本,请将 Compose BOM 版本升级为:

implementation(platform("androidx.compose:compose-bom:2026.04.01"))

Compose 1.11.0 中的变更

测试中的协程执行

我们将对 Compose 处理测试时间的方式进行重大更新。在 Compose 1.10 中宣布选择启用期后,v2 测试 API 现在已成为默认 API,而 v1 API 已被弃用。主要变化是默认测试调度程序的转变。v1 API 依赖于立即执行协程的 UnconfinedTestDispatcher,而 v2 API 使用 StandardTestDispatcher。这意味着,在测试中启动协程时,该协程现在会排队,直到虚拟时钟前进时才会执行。

这样可以更好地模拟生产环境,有效消除竞态条件,并显著提高测试套件的稳健性,减少不稳定情况。

为确保您的测试符合标准协程行为并避免日后出现兼容性问题,我们强烈建议您迁移测试套件。如需了解 API 映射和常见修复,请参阅我们的全面迁移指南

共享元素改进和动画工具

我们还添加了一些实用的可视化调试工具,用于调试共享元素和 Modifier.animatedBounds。现在,您可以准确地看到幕后发生的情况,例如目标边界、动画轨迹以及找到的匹配项数量,从而更轻松地发现过渡可能未按预期运行的原因。如需使用新工具,只需使用 LookaheadAnimationVisualDebugging 可组合函数将 SharedTransitionLayout 封装起来即可。

LookaheadAnimationVisualDebugging(
    overlayColor = Color(0x4AE91E63),
    isEnabled = true,
    multipleMatchesColor = Color.Green,
    isShowKeylabelEnabled = false,
    unmatchedElementColor = Color.Red,
) {
    SharedTransitionLayout {
        CompositionLocalProvider(
            LocalSharedTransitionScope provides this,
        ) {
            // your content
        }
    }
}

触控板事件

我们改进了对触控板的撰写支持,包括内置笔记本电脑触控板、平板电脑可连接的触控板或外部/虚拟触控板。现在,基本的触控板事件通常会被视为 PointerType.Mouse 事件,从而使鼠标和触控板行为与用户预期更加一致。之前,这些触控板事件会被解读为 PointerType.Touch 的虚假触屏手指,从而导致用户体验混乱。例如,使用触控板点击并拖动会滚动,而不是选择。通过更改这些事件在最新版 Compose 中的指针类型,使用触控板点击和拖动将不再滚动。

我们还添加了对自 API 34 以来平台识别的更复杂的触控板手势的支持,包括双指滑动捏合Modifier.scrollable 和 Modifier.transformable 等组件会自动识别这些手势,以便在触控板上实现更好的行为。

这些更改改进了内置组件中触控板的行为,移除了冗余的触控容差,提供了更直观的拖放启动手势、文本字段中的双击和三击选择,以及文本字段中桌面样式的上下文菜单。

为了测试触控板行为,我们推出了新的测试 API performTrackpadInput,,可用于验证应用在与触控板搭配使用时的行为。如果您有自定义手势检测器,请验证各种输入类型(包括触摸屏、鼠标、触控板和触控笔)的行为,并确保支持鼠标滚轮和触控板手势。

beforeAndAfter.webp

合成主机默认值(Compose 运行时)

我们引入了 HostDefaultProviderLocalHostDefaultProviderHostDefaultKey 和 ViewTreeHostDefaultKey,以便通过 compose-runtime 直接提供宿主级服务。这样一来,库就不再需要依赖 compose-ui 进行查找,从而更好地支持 Kotlin Multiplatform。为了将这些值与组合树相关联,库作者可以使用 compositionLocalWithHostDefaultOf 创建一个 CompositionLocal,用于从宿主解析默认值。

预览封装容器

Android Studio 自定义预览是一项新功能,可让您精确定义 Compose 预览的内容显示方式。

通过实现 PreviewWrapperProvider 接口并应用新的 @PreviewWrapper 注释,您可以轻松注入自定义逻辑,例如应用特定的 Theme。该注释可应用于带有 @Composable@Preview@MultiPreview 注释的函数,提供通用的易用型解决方案,适用于各种预览版功能,并可大幅减少重复代码。

class ThemeWrapper: PreviewWrapper {
    @Composable
    override fun Wrap(content: @Composable (() -> Unit)) {
        JetsnackTheme {
            content()
        }
    }
}

@PreviewWrapperProvider(ThemeWrapper::class)
@Preview
@Composable
private fun ButtonPreview() {
    // JetsnackTheme in effect
    Button(onClick = {}) {
        Text(text = "Demo")
    }
}

弃用和移除

  • 正如我们在 Compose 1.10 博文中所宣布的那样,我们即将弃用 Modifier.onFirstVisible()。它的名称经常会引起误解,尤其是在延迟布局中,它会在滚动期间多次触发。我们建议您迁移到 Modifier.onVisibilityChanged(),这样可以根据您的具体使用情形要求,更精确地手动跟踪可见性状态。
  • 移除了 ComposeFoundationFlags.isTextFieldDpadNavigationEnabled 标志,因为 TextFields 的方向键导航现在默认始终处于启用状态。新行为可确保来自游戏手柄或电视遥控器的方向键事件首先在给定方向移动光标。只有当光标到达文本末尾时,焦点才能移动到另一个元素。

即将推出的 API

在即将发布的 Compose 1.12.0 版本中,compileSdk 将升级到 compileSdk 37,并且依赖于 Compose 的 AGP 9 以及所有应用和库都将继承此要求。我们建议您及时更新到最新发布的版本,因为 Compose 旨在迅速采用新的 compileSdks,以便提供对最新 Android 功能的访问权限。请务必参阅此处的文档,详细了解不同 API 级别支持的 AGP 版本。

在 Compose 1.11.0 中,以下 API 作为 @Experimental 引入,我们期待您在应用中探索这些 API 时提供反馈。请注意,@Experimental APIs 仅用于早期评估和反馈,在未来的版本中可能会发生重大变化或被移除。

样式(实验性)

我们正在推出一项新的实验性基础 API,用于设置样式。样式 API 是一种用于自定义组件视觉元素的新范例,以前通常使用修饰符来实现。它旨在通过公开一组可设置样式的标准属性,并提供基于状态的简单样式设置和动画过渡效果,实现更深入、更轻松的自定义。借助这一新 API,我们已经看到了令人期待的性能优势。我们计划在样式 API 稳定后,在 Material 组件中采用样式。

替换按下状态样式背景的基本示例:

@Composable
fun LoginButton(modifier: Modifier = Modifier) {
    Button(
        onClick = {
            // Login logic
        },
        modifier = modifier,
        style = {
            background(
                Brush.linearGradient(
                    listOf(lightPurple, lightBlue)
                )
            )
            width(75.dp)
            height(50.dp)
            textAlign(TextAlign.Center)
            externalPadding(16.dp)

            pressed {
                background(
                    Brush.linearGradient(
                        listOf(Color.Magenta, Color.Red)
                    )
                )
            }
        }
    ){
        Text(
            text = "Login",
        )
    }
}
styles.webp

您可以查看文档,并在此处提交任何 bug。

MediaQuery(实验性)

新的 mediaQuery API 提供了一种声明式的高效方式,可让您根据界面所处的环境调整界面。它将复杂的信息检索抽象为 UiMediaScope 中的简单条件,确保仅在需要时进行重组。

通过支持各种环境信号(从键盘类型和指针精度等设备功能到窗口大小和设备姿态等情境状态),您可以打造深度自适应体验。derivedMediaQuery 内置了性能,可处理高频更新,同时能够替换范围,从而在各种硬件配置中实现无缝测试和预览。以前,若要访问某些设备属性(例如设备是否处于桌面模式),您需要编写大量样板代码:

@Composable
fun isTabletopPosture(
    context: Context = LocalContext.current
): Boolean {
    val windowLayoutInfo by
        WindowInfoTracker
            .getOrCreate(context)
            .windowLayoutInfo(context)
            .collectAsStateWithLifecycle(null)

    return windowLayoutInfo.displayFeatures.any { displayFeature ->
        displayFeature is FoldingFeature &&
            displayFeature.state == FoldingFeature.State.HALF_OPENED &&
            displayFeature.orientation == FoldingFeature.Orientation.HORIZONTAL
    }
}

@Composable
fun VideoPlayer() {
    if(isTabletopPosture()) {
        TabletopLayout()
    } else {
        FlatLayout()
    }
}

现在,借助 UIMediaQuery,您可以添加 mediaQuery 语法来查询设备属性,例如设备是否处于桌面模式:

@OptIn(ExperimentalMediaQueryApi::class)
@Composable
fun VideoPlayer() {
    if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) {
        TabletopLayout()
    } else {
        FlatLayout()
    }
}

您可以查看文档,并在此处提交任何 bug。

网格(实验性)

Grid 是一种强大的新 API,用于在 Jetpack Compose 中构建复杂的二维布局。虽然 Row 和 Column 非常适合线性设计,但 Grid 可为您提供屏幕级架构和复杂组件所需的结构控制,而不会产生可滚动列表的开销。Grid 可让您使用轨道、间隙和单元格定义布局,并提供熟悉的尺寸调整选项,例如 Dp、百分比、固有内容大小和灵活的“Fr”单位。

@OptIn(ExperimentalGridApi::class)
@Composable
fun GridExample() {
    Grid(
        config = {
            repeat(4) { column(0.25f) }
            repeat(2) { row(0.5f) }
            gap(16.dp)
        }
    ) {
        Card1(modifier = Modifier.gridItem(rowSpan = 2)
        Card2(modifier = Modifier.gridItem(colmnSpan = 3)
        Card3(modifier = Modifier.gridItem(columnSpan = 2)
        Card4()
    }
}

您可以自动放置商品,也可以明确指定商品跨越多个行和列,以实现精确放置。最重要的是,它具有高度的自适应性,您可以动态重新配置网格轨道和跨度,以响应桌面模式或屏幕方向变化等设备状态,从而确保界面在各种设备规格上都能呈现出色的外观。

Grid.gif

您可以查看文档,并在此处提交任何 bug。

FlexBox(实验性)

FlexBox 是一种布局容器,专为高性能自适应界面而设计。它会根据可用的容器尺寸管理商品尺寸和空间分布。它可处理复杂的任务,例如换行 (wrap) 和多轴对齐项 (justifyContent, alignItems, alignContent)。它允许项增大 (grow) 或缩小 (shrink) 以填充容器。

@OptIn(ExperimentalFlexBoxApi::class)
fun FlexBoxWrapping(){
    FlexBox(
        config = {
            wrap(FlexWrap.Wrap)
            gap(8.dp)
        }
    ) {
        RedRoundedBox()
        BlueRoundedBox()
        GreenRoundedBox(modifier = Modifier.width(350.dp).flex { grow(1.0f) })
        OrangeRoundedBox(modifier = Modifier.width(200.dp).flex { grow(0.7f) })
        PinkRoundedBox(modifier = Modifier.width(200.dp).flex { grow(0.3f) })
    }
}
AnimationGif.gif

您可以查看文档,并在此处提交任何 bug。

新的 SlotTable 实现(实验性)

我们推出了 SlotTable 的新实现,但在此版本中默认处于停用状态。SlotTable 是 Compose 运行时用于跟踪组合层次结构的状态、跟踪失效/重组、存储记忆的值以及在运行时跟踪组合的所有元数据的内部数据结构。此新实现旨在提升性能,主要是在随机编辑方面。

如需试用新的 SlotTable,请启用 ComposeRuntimeFlags.isLinkBufferComposerEnabled。 

立即开始编码!

Jetpack Compose 中有许多令人兴奋的新 API,而且还有更多 API 即将推出,现在无疑是迁移到 Jetpack Compose 的最佳时机。与往常一样,我们非常重视您的反馈和功能请求(尤其是针对仍在开发中的 @Experimental 功能),请点击此处提交。祝编程顺利!

作者:

继续阅读