产品资讯

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

5 分钟阅读时间
查看 Nick Butcher 的个人资料
Nick Butcher 产品经理

今天,Jetpack Compose 2026 年 8 月版已发布稳定版!此版本在核心 Compose 模块中引入了 1.12 版(请参阅完整的 BOM 映射),引入了丰富的视觉 API(例如网格渐变和广色域 (WCG) 支持)、结构布局功能(例如 Grid 中的命名区域)、与 Android 的 Credential Manager 的无缝集成,以及显著的测试和性能改进。

如需将项目更新到今天的版本,请将 Compose BOM 版本升级到 2026.08.00

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

重大变更

  • AGP 和编译 SDK :Compose 1.12 将 compileSdk 更新为 API 37,需要最低 AGP 9.1.2。提醒一下,Compose 将始终以最新的 compileSdk 为目标。如需详细了解此变更,请点击 此处
  • Modifier.onFirstVisible() 已弃用:请迁移到 Modifier.onVisibilityChanged(),后者可提供更精确的可见性阈值跟踪。

图形

网格渐变

Compose 1.12 引入了 MeshGradientPainter,可帮助您创建多点有机颜色渐变。

meshGradient.gif
val rows = 1
val columns = 1

val gradientPainter = remember {
    MeshGradientPainter(rows, columns) {
        // Parameters: row, column, position, color
        setVertex(0, 0, Offset(0f, 0f), Color.Red)     // Top-Left
        setVertex(0, 1, Offset(1f, 0f), Color.Blue)    // Top-Right
        setVertex(1, 0, Offset(0f, 1f), Color.Green)   // Bottom-Left
        setVertex(1, 1, Offset(1f, 1f), Color.Yellow)  // Bottom-Right
    }
}

Box(
    modifier = modifier
        .aspectRatio(16/9f)
        .fillMaxWidth()
        .paint(gradientPainter)
)

如需了解详情和示例,请参阅 文档

广色域和 HDR 支持

现代显示器可提供更高的色彩保真度和更高的动态范围。在 Compose 1.12 中,Compose 图形、绘制和着色器已启用对 广色域 (P3)HDR 渲染 的完整流水线支持。在非 sRGB 颜色空间(例如 Display P3)中定义的颜色会保留到平台渲染,而不会进行颜色钳制。如果颜色使用不受支持的颜色空间(例如 CieXyz、CieLab 或 Oklab)、依赖于不受支持的 Android 版本上的颜色空间(例如 Android 13 及更低版本上的 Bt2020Hlg),或者应用在 Android 9 (API 28) 及更低版本上运行,则颜色将安全地回退到 sRGB。

其他显著变更:

  • LayerOutsets 已添加到 GraphicsLayerModifier.graphicsLayer,您可以使用它将图层的视觉边界扩大到超出其测量大小。当图层升级到屏幕外缓冲区时,应用 LayerOutsets 以避免隐式 clipToBounds 行为。

样式

在 Google I/O 大会上,我们分享了对 Compose Styles API(一种用于设置组件样式的统一高效方式)的早期愿景。此后,我们继续构建底层架构,以保证严格的类型安全性和可预测的正确性,并支持构建自定义设计系统。

为确保此基础层正确无误,该 API 将保持实验性状态,并且您可能会遇到重大变更。

运行时优化

键控 SideEffect 重载

SideEffect 现在支持键实参,让您可以在特定键发生更改时触发一次性副作用。与使用 LaunchedEffectDisposableEffect 相比,当您不需要协程或处置块时,这可以带来更好的性能。SideEffectLaunchedEffect 快 90%,比 DisposableEffect 快 20% 左右。请注意,SideEffect 会在 DisposableEffectLaunchedEffect 之前运行其效果,因此,如果将现有效果迁移到此 API,请谨慎操作,尤其是对于依赖于在当前帧完成后分派以启动的 LaunchedEffects

@Composable
fun AnalyticsTracker(userId: String, screenName: String) {
    SideEffect(key1 = userId, key2 = screenName) {
        analytics.logScreenView(userId, screenName)
    }
}

动画

互动式两阶段转换

  • 新的可组合项DeferredAnimatedContentDeferredAnimatedVisibility 允许创建令人愉悦的两阶段转换,例如用于预测性返回手势跟踪。
  • 手动动画控制:在转换的延迟阶段,现在可以实时手动操作动画属性(例如缩放或偏移量)(例如,跟踪滑动操作)。
  • 无缝移交:延迟阶段结束后,转换引擎会接管并执行无缝移交(包括速度转移)到自动转换。
  • 共享元素支持permitTransformDuringDeferredTransition 中的新 SharedContentConfig 标志控制着共享元素在延迟转换阶段是否与其父容器一起进行视觉转换。
val state = remember { DeferredTransitionState(initialScreen) }
val transition = rememberDeferredTransition(state)

if (predictiveBackInProgress) {
    state.defer(targetScreen)
} else {
    state.animateTo(targetScreen)
}

transition.DeferredAnimatedContent(
    targetState = targetScreen,
    mutableTransformSpec = {
       MutableContentTransform {
           // Manually manipulate properties during the deferred phase
           initialContentTransform { scale = swipeProgress }
       }
    }
) { screen ->
    ScreenContent(screen)
}

以下是两个演示,展示了手势驱动的动画移交给触发的动画的用例:

colorCards.gif

文本、输入和平台集成

可编辑文本格式

新 API 为 BasicTextField 中的可编辑文本提供了富文本格式。您现在可以使用 SpanStyleParagraphStyle,通过 TextFieldBuffer 范围(例如 textFieldState.edit { ... }InputTransformation 内)中的新 addStyle() 方法,以编程方式应用和操作内嵌字符和段落格式。此外,TextFieldBuffer 还提供了 getSpanStyles()getParagraphStyles() API,它们会返回 TrackedRange 对象,让您可以读取、更新或移除已应用的样式。为了补充格式创建,TextFieldState 现在公开了一个只读 textStyles 属性,用于查询范围内的活跃样式,而 TextFieldBuffer 则提供了 originalTextStyles 来检查编辑之前的格式状态。文本格式和自定义注解会在配置更改期间保留。

val state = rememberTextFieldState("Formatted text in Compose 1.12")

// Apply bold and color styles to a range of text
state.edit {
    addStyle(
        SpanStyle(fontWeight = FontWeight.Bold, color = Color.Blue),
        start = 0,
        end = 9
    )
}

// Query active styles from TextFieldState
val currentStyles = state.textStyles

文本选择

新的 SelectionState API 提供了对 SelectionContainer 中文本选择的编程控制和可观测性。通过 rememberSelectionState() 提升 SelectionState 对象并将其传递到 SelectionContainer,会将 selectedTexts 公开为 AnnotatedStrings 的响应式列表,并提供 selectAll()clear()select(TextRange)extendSelectionByWord() 等方法。

此外,您还可以使用 getSelectableTexts() 按布局顺序检索所有可选择的文本项,并使用全局范围在 SelectionContainer 中跨可组合项选择文本。

@Composable
fun ProgrammaticSelectionExample() {
    val selectionState = rememberSelectionState()

    Column {
        Button(
            onClick = { selectionState.selectAll() },
            modifier = Modifier.disableSelectionClearOnTap()
        ) {
            Text("Select All")
        }

        SelectionContainer(state = selectionState) {
            Text("Text content to be selected programmatically.")
        }
    }
}

Credential Manager 集成

Compose 文本字段现在通过自动填充框架(API 34 以下版本由 androidx.credentials library 处理)与 Android 的 Credential Manager (API 34+) 原生集成。通过将新的 credentialRequest 语义属性与 CredentialRequestData 相关联,文本输入可以直接在用户输入流程中提示通行密钥、已保存的凭据或登录请求。

@Composable
fun LoginField(textFieldState: TextFieldState) {
    val credentialData = remember {
        CredentialRequestData(
            // Specify Credential Manager request options
        )
    }

    BasicTextField(
        state = textFieldState,
        modifier = Modifier.semantics {
            credentialRequest = credentialData
        }
    )
}

其他显著变更:

  • 支持 可下载字体中的字体变体设置。
  • SelectionContainer 中将文本选择拖动到视口之外时,启用了自动滚动。
  • 为 Compose 组件添加了对自动互动声音(点击和焦点导航)的支持,并提供了一个新的 SoundEffectOnInteraction 可组合项以允许选择停用。请注意,由于此变更,语义点击监听器现在必须从主线程调用,这可能会影响少量测试用例。
  • KeyboardType 现在包含 DateTimeDateTimeSignedDecimal
  • BasicSecureTextField 现在默认使用 TextObfuscationMode.System,而 RevealLastTyped 则作为绝对替换。

布局增强功能

网格布局中的命名区域

借助 @Experimental Grid 组件中的命名区域,现在可以更轻松地构建复杂的 2D 布局。您无需跨项管理数字列和行索引,而可以在 GridConfigurationScope 中定义语义区域,并按区域名称定位可组合项。

@OptIn(ExperimentalGridApi::class)
@Composable
fun DashboardLayout() {
    Grid(
        config = {
            area("header", row = 0, column = 0, rowSpan = 1, columnSpan = 2)
            area("sidebar", row = 1, column = 0)
            area("content", row = 1, column = 1)
            gap(16.dp)
        }
    ) {
        HeaderSection(modifier = Modifier.gridItem(areaId = "header"))
        NavigationSidebar(modifier = Modifier.gridItem(areaId = "sidebar"))
        MainContentView(modifier = Modifier.gridItem(areaId = "content"))
    }
}

如需了解详情,请参阅文档

性能

与每个版本一样,我们会继续投资于 Compose 的性能,以确保该框架可帮助您构建美观且高性能的应用。在此版本中,我们专注于提升启动性能,现在看到的初步显示用时(应用生成第一帧所用的时间)与 基准中的 View 相当。

timetoinitialdisplay@2x _v2.png

测试和工具升级

测试同步

Compose 1.12 引入了新的测试 API,旨在缩短测试作业时间并消除状态采样期间的不稳定性:

  • hasPendingWork:被动检查界面是否有待处理的工作,而无需推进时钟,这非常适合手动动画循环。
  • runWithoutImplicitWait:在逐步执行手动时钟帧(例如动画测试)时,暂时停用隐式同步。
@Test
fun testAnimationStateFast() {

composeTestRule.mainClock.autoAdvance = false
    
    while (composeTestRule.hasPendingWork()) {
        composeTestRule.mainClock.advanceTimeByFrame()
        composeTestRule.waitForIdle()
        
        composeTestRule.runOnUiThread {
            composeTestRule.runWithoutImplicitWait {
                // This is most effective when querying multiple nodes in a single frame. 
                // It prevents the redundant synchronization overhead that would 
                // otherwise occur on every individual query.
                val box1 = composeTestRule.onNodeWithTag("Box1").fetchSemanticsNode()
                val box2 = composeTestRule.onNodeWithTag("Box2").fetchSemanticsNode()
                
                assertThat(box1.boundsInRoot.right).isAtMost(box2.boundsInRoot.left)
            }
        }
    }
}

其他显著变更:

  • 借助 captureToImage API,您现在可以在单个位图中捕获弹出式窗口或对话框及其锚点。
  • 添加了 onRootWithViewInteraction,以将 Compose 语义搜索限定为特定的 Android View。这简化了混合界面(例如 RecyclerViews)的测试,而无需在生产代码中使用唯一的测试标记。
  • @PreviewWrapper 注解现在可以应用于自定义 @MultiPreview 类,从而在多个组件中启用可重复使用的预览设置(例如自定义主题)。

祝编程顺利!

Compose 1.12 借助网格渐变、广色域支持、可下载的可变字体、Credential Manager 集成和更快的测试工具,让应用开发比以往更加轻松且富有表现力。与往常一样,我们重视您的意见和建议,因此请在 问题跟踪器上分享您对此类变更的反馈,或您希望接下来看到的内容。祝编程顺利!

继续阅读