折叠屏
苹果在秋季发布会上推出了首款折叠屏 iPhone——iPhone Duo。展开屏幕,正在浏览的页面有了更多空间;合上屏幕,内容又回到较小的窗口。用户期待的,是页面能顺着屏幕的变化自然调整。
Lynx 已经支持折叠屏适配,并在 TikTok 中投入使用。我们希望接入尽可能简单:客户端把尺寸变化同步给 Lynx,前端继续使用熟悉的布局方式,让页面随窗口大小自动调整。

折叠

展开
全新的屏幕尺寸
适配从客户端开始。窗口尺寸变化后,客户端先完成原生布局,再一并更新 Lynx 的 screen metrics、viewport 和 GlobalProps,让引擎的布局基准和前端读取的尺寸保持一致。
先看尺寸如何传给前端。GlobalProps 负责将客户端的环境信息传给页面,前端通过 lynx.__globalProps 读取。在 TikTok 中,我们用两组字段分别表示窗口尺寸和页面实际可用的尺寸,供社区参考:
这些字段由客户端自行定义,单位统一为逻辑像素,即 Lynx CSS px,在 iOS 上对应 pt。首次加载时,通过 LynxLoadMeta.globalProps 设置初始值;之后随尺寸变化更新各个 LynxView 实例,前端只负责读取。
运行时更新 GlobalProps,传入的字段会合并到已有数据中,并触发 onGlobalPropsChanged。在默认的 globalPropsMode: 'reactive' 下,ReactLynx 会自动对整个页面重新执行 render,组件在 render 时读取最新尺寸即可。如果选择 'event' 模式,则不会自动触发整页 render。
客户端同时更新的 screen metrics 和 viewport,分别为 rpx 和 vw、vh 提供尺寸基准。ReactLynx 通过 Element PAPI 将 UI 变化应用到 Element 树,随后引擎根据新尺寸解析样式、完成布局(Layout),最后由平台绘制画面。
- 客户端更新screen metricsviewportGlobalProps同步最新尺寸
- ReactLynx自动执行整页 render读取最新尺寸,计算 UI 差异
- Element PAPI应用差异,更新 Element 树
- Resolve · Layout解析样式,计算节点大小和位置
- Paint执行 UI 更新,绘制新画面
在 iOS 上,分别调用 updateScreenMetricsWithWidth:height:、updateViewport 和 updateGlobalPropsWithDictionary 完成这三项更新。调用时,视图应已加入窗口并完成原生布局,且这些操作都要在主线程执行。下面的示例用窗口尺寸更新 screen metrics,用 LynxView 自身的尺寸更新 viewport:
创建 LynxView 时,也要通过 LynxViewBuilder.screenSize 设置相同的 rpx 基准;后续尺寸没有变化时,无需重复更新。更新 screen metrics 本身不会触发布局,因此示例在更新 viewport 时设置了 needLayout:YES。如果启用了 enableAutoLayout,视口则会随布局约束自动更新。
熟悉的布局单位
客户端完成这些接入后,前端通常只需很少的适配工作。对于已经使用弹性布局和相对单位的页面,前端无需感知折叠状态,也无需手动触发更新,页面就能随可用空间的变化自动调整布局。
写页面时,仍然只需考虑熟悉的问题:这个尺寸应该跟随父容器、整个视口,还是文字大小?选好参照,现有的响应式布局就能适应新的屏幕尺寸。
下表整理了各个单位的尺寸基准,以及客户端完成接入后,它们能否随基准变化自动调整。
实际布局时,可以用 Flex 和 width: 100% 让内容随容器伸缩,再用 max-width 避免内容在大屏上拉得过宽。字号、按钮大小和间距可以继续使用合适的 px 值。这样,内容区域可以变宽,文字和控件仍保持熟悉的大小。
rpx 的尺寸取决于 screen metrics:1rpx 等于其中配置的逻辑宽度的 1/750。客户端更新 screen metrics 后,Lynx 会在布局时自动重新计算 rpx 对应的尺寸,前端无需自行换算。
各单位的详细说明可参阅长度单位。