3.2 多设备适配与高级 UI 能力


3.2 多设备适配与高级 UI 能力

本节摘要:用 List 与 ForEach 搭建可滚动长列表并理解懒加载,用 GridRow/GridCol 栅格与断点实现"一多"(一次开发、多端部署)的响应式界面,顺带引入 Swiper、自定义绘制等高级 UI 能力,让同一份代码在手机与平板呈现两种形态。

同一份代码,三种屏幕

"一次开发,多端部署"落到界面层,就是同一份 ArkTS 代码要在小到手表、大到平板的屏幕上都有体面的形态。HarmonyOS 提供的解法分三层,自底向上是:自适应布局(组件自己伸缩,如 layoutWeight、百分比尺寸)——解决尺寸连续变化;栅格断点(GridRow/GridCol 按屏幕宽度切列数)——解决形态档位切换;多设备分发(按设备类型加载不同页面)——解决形态彻底不同。前两层覆盖九成场景,本节聚焦它们。

先看自适应层做不了什么。假设你在手机上写了一个两列的信息列表,用 Row 放两个卡片各占一半;到平板上,两个半宽卡片会被拉成两张巨幅卡片,能用但难看。这不是 bug,是"连续伸缩"无法产生"布局重构"。要档位感,必须引入断点。

图:断点之上一份代码的三种形态

图:断点之上一份代码的三种形态

栅格的用法:GridRow 是断点容器,GridCol 是断点内的格子,span 与 offset 都可以按断点分别指定:

GridRow({ breakpoints: { value: ['600vp', '840vp'], reference: BreakpointsReference.WindowSize } }) { GridCol({ span: { sm: 4, md: 2, lg: 2 } }) { this.articleCard('第一章') } GridCol({ span: { sm: 4, md: 2, lg: 2 } }) { this.articleCard('第二章') } }

栅格默认 4 列(可改 6 或 8):sm 下每卡占满 4 列即单列;md 下各占 2 列变双列;lg 下保持双列但配合更宽的边距。把这段替换进你首页的外层容器,然后创建一个平板模拟器(Device Manager 里可选平板形态)分别运行——同一份代码,两种形态,这就是"一多"的现场感。

长列表与懒加载

内容多了就要滚动,滚动的正主是 List。最小可用版本:

List({ space: 8 }) { ForEach(this.articles, (item: Article) => { ListItem() { this.articleCard(item.title) } }, (item: Article) => item.id.toString()) } .listDirection(Axis.Vertical) .width('100%') .edgeEffect(EdgeEffect.Spring)

三个必讲细节。其一,ForEach 的第三个参数是键值生成器——用稳定唯一的业务 id,不要用数组下标。键值是框架识别"哪一项变了"的依据,用下标时插入删除会让框架误判大量变更,列表闪烁与性能劣化都源于此。其二,List 自带滚动,不要再套 Scroll;两者嵌套是新手列表"滚动卡顿"的经典来源。其三,ForEach 在 List 里默认按需创建组件(懒加载),千行数据也只有屏幕附近的几十行参与渲染;但若把 ForEach 用在 Column 里,则全量创建——长列表必须用 List 承载,这属于"用对容器"而非"调优"。

进阶的 LazyForEach 需要配合数据源对象(实现接口返回总数与按需取数),在万行级或分页加载场景再上;先把 ForEach 与键值的纪律做好,多数应用的列表性能已经够用。

高级 UI 能力速览

三个高频的高级能力,各给一个"什么时机该想起它":

Swiper 轮播:首页 banner、引导页。autoplay 与 indicator 两行属性就能跑起来,子项通常是 ForEach 生成的 Image。手势联动由框架处理,不必自己写触摸逻辑。

自定义绘制 Canvas:图表、不规则进度。Canvas 提供 2D 画布 API,在 onReady 回调里画;简单的圆环进度用两个 Circle 加描边就能拼出。判断标准:Shape 系组件能拼出来的,优先用 Shape(声明式、可参与布局动画),拼不出来的自由绘图才上 Canvas。

动画:属性动画用 animateTo 包住状态修改,或给组件挂 animation 属性(指定监听哪些属性变化)。布局类动画(位置尺寸变化)用 transition 配合出现消失。动画细节能单独成章,本教程只要求掌握 animateTo 包状态这一招,第 8 章谈性能时会再提"动画别碰布局属性"的原则。

演练:把首页重构成响应式列表

背景:应用首页现在有 6 张文章卡片竖排在 Column 里,平板上稀疏难看。操作:外层换成 GridRow(断点 600/840),卡片包进 GridCol(span 按断点 4/2/2);卡片内容重排——Row 头图加 Column 标题摘要,头图固定 96vp 宽。结果:手机单列大卡,平板双列中卡,均无拉伸变形。解读:这次重构没有写一行 if 判断设备类型,形态切换完全由栅格按宽度驱动——这正是自适应布局优于手动分支的地方。变式:给卡片加 onClick 进详情(页面路由第 4 章后可用 router 或 Navigation,届时把这个入口接上)。

⚠️ 常见坑:给 List 的子项设了固定高度又指望它自适应屏幕,结果小屏溢出、大屏留白。容器尺寸策略要统一:要么内容自适应(不设高度),要么比例弹性(layoutWeight/百分比),避免"固定值混弹性"。

💡 关键直觉:适配的优先级是"自适应布局先行,栅格断点其次,多页面分发兜底"。前两层解决不了的形态差异(比如手表上的完全不同交互)才值得付出第三层的维护成本。

本节要点回顾:

  • 一多三层解法:自适应布局管连续伸缩,栅格断点管档位切换,多页面分发兜底形态重构。
  • GridRow/GridCol:span 按断点分别指定,4 列栅格是最常用配置。
  • List 纪律:不套 Scroll、键值用业务 id、长列表必须 List 承载懒加载。
  • 高级能力时机:轮播想 Swiper,自由绘图想 Canvas,能拼则 Shape;动画先会 animateTo。
  • 容器选型回顾:上一节的选型矩阵加上本节断点,构成布局设计的完整工具箱。

界面层的手艺到此告一段落。下一章进入数据的世界:状态如何在组件树里定义、传递与共享,V1 与 V2 两套体系如何取舍——这是声明式应用的核心机枢。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U