Compose Multiplatform 1.10 Interop views 新特性:Overlay 和 Autosizing

近日,在 CMP 的 1.10 更新里,官方提及了两个关于 Interop views 的全新特性:Overlay 和 Autosizing ,核心目的就是解决 Compose Multiplatform 在"嵌入原生 UI 组件(interop views)"时最头疼的两件事:层级(z-order)和尺寸(measure/layout)

Interop View ≈ Flutter 里的 PlatformView 。

一、Overlay

Overlay placement for interop views 的主要作用就是:让 UIKit interop 真正能"盖在"Compose 上

kotlin 复制代码
@OptIn(ExperimentalComposeUiApi::class)
UIKitViewController(
    modifier = modifier,
    factory = { factory.createNativeMap() },
    update = {},
    properties = UIKitInteropProperties(placedAsOverlay = true)
)

在过去,我们可以使用 UIKitView / UIKitViewController 把 iOS 原生控件嵌到 Compose 里,而这次 1.10 增加了一个 实验性开关:UIKitInteropProperties.placedAsOverlay = true,主要目的就是让这些 UIKit interop 视图可以放在 Compose UI 之上

核心目的就是 interop view 可以更好地支持透明背景和原生 shader / 特效 ,这对于现在全新的 iOS 26 Liquid Glass 场景来说尤为重要。

简单来说,在之前,iOS 上的 interop view 更像 Underlay ,不严谨的说,就类似 : UIKit 在下,Compose 在上,Compose 需要"让出一个洞/区域"让 UIKit 露出来

因为 Compose (Skia) 和 UIKit view 不在同一渲染树里,所以默认 interop 实现更偏向"在 Compose 里留出空间让 UIKit 显示",所以视觉效果就像 hole punching。

这种情况下 iOS 的 Interop views 无法实现毛玻璃/半透明覆盖,因为原生 View 在下面,你无法让原生 View 变成半透明盖在 Compose 内容上。

所以你会发现,在之前,当你需要 blur 的时候,看到的不是 Compose 而是黑底或 window 底色" ,这是因为 "UIKit 的半透明/blur 采样不到 Skia 的内容" 。

而现在 1.10 提供了新的可能,interop view 可以通过配置提升到 Compose/Skia 渲染层上方成为真正的 overlay,这时候原生半透明背景、shader、blur 等效果就可以正确叠加在 Compose 上,当然,同时代价是同区域 Compose 可能会被遮挡/点击被原生 view 吃掉。

虽然实现上不是 Flutter HC 那种合成路径,但是表现形式上和类似。

总结一下就是:之前 iOS 上的 interop view 只能做"底图",不能做"蒙层" ,现在可以开始追求 iOS 原生质感的效果了

Autosizing

从 1.10 开始,CMP 对 interop view 加了 Autosizing :

  • Desktop(Swing)SwingPanel 会根据嵌入 Swing 组件的 minimum / preferred / maximum size 自动调整自身尺寸
  • iOS(UIKit) :UIKit interop view 支持按视图的 fitting size / intrinsic content size 来决定大小,从而能更好地 wrap content

简单说就是:你不用再手算尺寸、也不用提前写死宽高

并且特别提到一个大痛点的解法:在 iOS 上,这让你通过 UIHostingController 包 SwiftUI 的时候,更容易做到正确的"内容包裹"。

为什么这又是一个大更新内容?因为在 Compose 的世界里,布局是"先测量、再布局",而过去 interop view 最大的问题是:

  • Compose 不知道原生 view 的"理想尺寸",导致常常必须:
    • Modifier.size(...) 写死;
    • 或者自己去桥接 native 的测量逻辑,再把结果喂给 Compose
  • 一旦内容变化(比如 SwiftUI 文本变化、Swing 组件 preferredSize 变了),还要触发重算

Autosizing 相当于把 interop 的测量链路补齐了,让 interop 更接近 Compose 原生组件的体验:能 wrap content,能随内容变化而重新测量

这个基础上,SwiftUI 视图(通过 UIHostingController )和不依赖 NSLayoutConstraints 的 basic UIView 子类能更方便适配封装。

也就是说这个更新,可以简化了混合开发时的布局工作,让原生组件能像 Compose 原生组件一样自然地"撑开"布局。

最后

至于你肯定会说,那为什么不说 Andorid ?那肯定是因为 CMP 是基于 Compose 实现的啊,Compose Android 本质上还是嵌在 Android View 系统里,ComposeView 是一个 Android View,跑在同一个 View hierarchy 里:

Compose 和 Android View 一开始就属于同一个"生态",同一种坐标系、同一种生命周期、同一种事件分发。

所以当你用 AndroidView {} 嵌一个原生 View 的时候,它没有"Skia vs UIKit 两个体系隔离"这种割裂,最典型的就是 SurfaceViewAndroidView 里可以正常工作:

Compose 和「传统 View」 共用同一个 Window 和 DecorViewAndroidView 作为一个桥接节点,将「传统 View」 "插入" 到 Compose 的布局树中,虽然 SurfaceView 绘制内容是独立的,但在屏幕上是共享一个 WindowSurfaceFlinger 依然会统一管理窗口合成。

这部分在之前的 《深入 Flutter 和 Compose 的 PlatformView 实现对比,它们是如何接入平台控件》 有了聊过,感兴趣可以看看。

参考链接

https://kotlinlang.org/docs/multiplatform/whats-new-compose-110.html

相关推荐
消失的旧时光-19432 小时前
Flutter ListView 全解:从 RecyclerView 到声明式列表
flutter
世人万千丶2 小时前
鸿蒙跨端框架Flutter学习day 1、变量与基本类型-智能家居监控模型
学习·flutter·ui·智能家居·harmonyos·鸿蒙·鸿蒙系统
小白阿龙2 小时前
flutter 与鸿蒙融合开发实战:构建跨平台应用的新范式
flutter·华为·harmonyos
世人万千丶2 小时前
鸿蒙跨端框架Flutter学习day 1、变量与基本类型-咖啡店点餐逻辑
学习·flutter·ui·交互·鸿蒙·鸿蒙系统
胖虎12 小时前
Android 文件下载实践:基于 OkHttp 的完整实现与思考
android·okhttp·下载文件·安卓下载·安卓中的下载
_李小白2 小时前
【Android 美颜相机】第四天:CameraLoader、Camera1Loader 与 Camera2Loader
android·数码相机
00后程序员张2 小时前
iOS APP 性能测试工具,监控CPU,实时日志输出
android·ios·小程序·https·uni-app·iphone·webview
YIN_尹2 小时前
【MySQL】数据类型(下)
android·mysql·adb
菜鸟小芯3 小时前
【开源鸿蒙跨平台开发先锋训练营】Day2 OpenHarmony版Flutter 3.27版本开发环境搭建
flutter·harmonyos