产品资讯

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

阅读用时:6 分钟
查看 Meghan Mehta 的个人资料
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
        }
    }
}

触控板事件

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

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

这些更改改进了触控板在内置组件中的行为,移除了多余的触摸溢出,提供了更直观的拖放起始手势、文本字段中的双击和三击选择,以及文本字段中的桌面式上下文菜单。

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

beforeAndAfter.webp

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

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

预览封装容器

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

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

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


@PreviewWrapper(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,AGP 9 以及依赖 Compose 的所有应用和库都将继承此要求。我们建议您及时了解最新发布的版本,因为 Compose 旨在及时采用新的 compileSdks,以便提供对最新 Android 功能的访问权限。请务必参阅此处的文档,详细了解不同 API 级别支持的 AGP 版本。

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

样式(实验性)

我们将推出一个用于样式设置的全新实验性基础 API。Style API 是一种用于自定义组件视觉元素的新范式,传统上,这些元素是通过修饰符进行自定义的。它通过提供一组标准的可样式化属性,并支持基于状态的简单样式设置和动画过渡,旨在实现更深入、更轻松的自定义。借助这个新 API,我们已经看到了可喜的性能优势。一旦 Style 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 功能),请点击此处提交。祝编程顺利!

作者:
继续阅读