Kotlin Multiplatform Development Help

Compose Multiplatform 1.8.0-beta02 的新特性

以下是本次EAP功能版本的重点内容:

  • 可变字体

  • iOS拖放功能

  • iOS无障碍功能改进

  • Web目标的资源预加载

  • 导航库与浏览器控制集成

完整变更列表请查看GitHub发布页

破坏性变更

Compose Multiplatform全面迁移至K2编译器

此版本中,Compose Multiplatform代码库已完全迁移至K2编译器。从1.8.0开始,依赖Compose Multiplatform的项目生成的native和web klibs仅能在Kotlin 2.1.0及以上版本中使用。

对项目的影响(除Compose编译器Gradle插件的底层变更外):

  • 依赖Compose Multiplatform的库 :需将项目升级至Kotlin 2.1.x和Compose 1.8.0,重新编译库并发布新版本。

  • 使用此类库的应用 :建议将项目升级至Kotlin 2.1.20,并将依赖更新为基于Compose Multiplatform 1.8.0和Kotlin 2.1.x编译的版本。

若升级至Compose Multiplatform 1.8.0时遇到兼容性问题,请在YouTrack提交问题报告。

导航库从Bundle迁移至SavedState

Compose Multiplatform 1.8.0-beta02的导航功能与Android Navigation组件共同转向使用SavedState类存储UI状态。这改变了在导航图中声明目的地时访问状态数据的模式。升级至Navigation库2.9.*版本时,请确保更新此类代码以使用SavedState的访问器。

迁移前代码:

composable(Destinations.Followers.route) { navBackStackEntry -> val uId = navBackStackEntry.arguments?.getString("userid") val page = navBackStackEntry.arguments?.getString("page") if (uId != null && page != null) { FollowersMainComposable(navController, accountId = uId, page = page) } }

Compose Multiplatform 1.8.0-beta02起:

composable(Destinations.Followers.route) { navBackStackEntry -> val uId = navBackStackEntry.arguments?.read { getStringOrNull("userid") } val page = navBackStackEntry.arguments?.read { getStringOrNull("page") } if (uId != null && page != null) { FollowersMainComposable(navController, accountId = uId, page = page) } }

iOS平台弃用ComposeUIViewControllerDelegate

ComposeUIViewControllerDelegate API已被弃用,推荐改用父视图控制器。若在Compose Multiplatform 1.8.0-beta02中使用该API,将收到提示应通过父视图控制器重写UIViewController类方法的弃用错误。详情参阅Apple开发者文档

移除iOS过时的platformLayers选项

实验性选项platformLayers1.6.0引入 )用于启用替代分层模式,在父容器边界外绘制弹窗和对话框。该模式现已成为iOS默认行为,相关选项已被移除。

测试相关破坏性变更

测试中协程延迟的新处理方式

此前Compose Multiplatform测试不会将包含delay()调用的副作用视为空闲状态。例如以下测试会无限挂起:

@Test fun loopInLaunchedEffectTest() = runComposeUiTest { setContent { LaunchedEffect(Unit) { while (true) { delay(1000) println("Tick") } } } }

现当组合作用域内启动的协程调用delay()后, waitForIdle()awaitIdle()runOnIdle()会将Compose视为空闲状态。此变更修复了上述测试挂起问题,但会破坏依赖这些函数执行含delay()协程的测试。此时需手动推进时间:

var updateText by mutableStateOf(false) var text by mutableStateOf("0") setContent { LaunchedEffect(updateText) { if (updateText) { delay(1000) text = "1" } } } updateText = true waitForIdle() // 由于waitForIdle()不再等待含延迟的LaunchedEffect完成 // 测试需推进时间以保证断言正确: mainClock.advanceTimeBy(1001) assertEquals("1", text)

runOnIdle()实现与Android对齐

为统一行为:

  • runOnIdle()现会在UI线程执行action

  • 执行action后不再自动调用waitForIdle()

若测试依赖该额外调用,升级时需手动添加。

测试时间推进与渲染解耦

mainClock.advanceTimeBy()不再触发重绘(除非时间推进超过下一帧的16ms间隔)。可能影响依赖每次调用触发渲染的测试,详见PR说明

跨平台功能

可变字体

所有平台现支持可变字体,单个字体文件可包含字重、宽度、斜度等样式变体。详见Jetpack Compose文档

Skia升级至Milestone 132

通过Skiko使用的Skia版本已更新,变更详见发布说明

行高对齐

原Android专属的行高对齐API现全平台可用。通过LineHeightStyle.Alignment可配置文本在行高空间内的对齐方式(顶/中/底/按升降部比例)。Material3组件默认使用居中对齐。

行高对齐示例

iOS平台

拖放功能

新增拖放支持,可通过dragAndDropSourcedragAndDropTarget修饰符定义可拖拽内容和放置目标。拖放数据使用UIDragItem表示,当前仅支持StringNSObject类型。用例参考Jetpack Compose文档

无障碍功能改进

右到左语言支持

新增对从右到左语言的无障碍支持,包括手势文本方向处理。

可滚动列表无障碍

改进滚动边界和元素位置计算的准确性,支持安全区域(如刘海屏边缘)。新增滚动状态语音提示("First page"/"Next page"等),含多语言版本。

容器视图无障碍

可为容器定义遍历语义属性,确保屏幕阅读器正确读取复杂视图。例如通过traversalIndex = -1f使悬浮按钮优先聚焦。

可访问文本输入

文本字段现标记为可编辑状态,支持无障碍测试。

触控板与键盘控制

新增两种输入方式支持:

  • AssistiveTouch (设置-辅助功能-触控):通过外接鼠标/触控板控制

  • 全键盘控制 (设置-辅助功能-键盘):通过外接键盘导航

按需加载无障碍树

改为惰性同步机制,首次请求时完整加载,交互停止后释放。移除不再需要的AccessibilitySyncOptions类。

无障碍属性计算优化

组件属性现与UIKit行为一致,透明组件(alpha=0)不再提供无障碍语义。修复了下拉菜单点击区域、文本标签不匹配等问题。

iOS日志API稳定化

enableTraceOSLog()不再需要实验性标记,日志格式与Android对齐,可通过Xcode Instruments分析。

并发渲染选项

支持将渲染任务分流至专用线程(需无UIKit交互场景)。通过ComposeUIViewControllerConfigurationuseSeparateRenderThreadWhenPossibleparallelRendering启用:

@OptIn(ExperimentalComposeUiApi::class) fun main(vararg args: String) { UIKitMain { ComposeUIViewController(configure = { parallelRendering = true }) { // ... } } }

Web平台

资源预加载

新增实验性API防止字体/图片加载闪烁:

  • preloadFont() :预加载字体

  • preloadImageBitmap() :预加载位图

  • preloadImageVector() :预加载矢量图

详见文档

导航库支持浏览器控制

Kotlin/Wasm和JS应用现可通过window.bindToNavigation()绑定导航历史,支持浏览器前进/后退按钮和地址栏路由同步。可选参数getBackStackEntryPath支持自定义路由转URL片段逻辑。

浏览器光标设置

新增PointerIcon.Companion.fromKeyword()实验函数,支持通过CSS关键字设置鼠标指针样式。

桌面平台

Windows ARM64支持

JVM目标现支持ARM架构的Windows设备。

Gradle插件

androidLibrary目标的多平台资源支持

适配Android Gradle插件8.8.0,支持将多平台资源打包为Android资产。使用androidLibrary目标时需启用配置:

kotlin { androidLibrary { experimentalProperties["android.experimental.kmp.enableAndroidResources"] = true } }

否则会抛出MissingResourceException异常。

23 四月 2025