news 2026/10/28 1:57:24

【共创稿事节】从手机到 2in1:一个菜谱应用的三断点适配实录

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【共创稿事节】从手机到 2in1:一个菜谱应用的三断点适配实录

一、为什么个人项目也要认真做适配

个人开发者最容易把"多设备适配"当成大厂的事——反正用户主要在手机上。但 module.json5 里一行 deviceTypes 就决定了你的应用出现在哪些设备上:写了三个设备却只按手机调布局,等于自愿在平板和电脑上呈现半成品。而且鸿蒙的生态现实是折叠屏、平板、2in1 的用户重合度越来越高,适配欠账迟早要还。

"健康菜谱助手"的 module.json5 里声明了三种设备:

"deviceTypes": ["phone", "tablet", "2in1"]

这一行的含义是:应用包要能在手机、平板、2in1(鸿蒙电脑形态)上安装运行。声明的瞬间,适配就从"可选项"变成了"义务"——2in1 上窗口可以自由拉伸,平板上有分屏,手机上有折叠屏展开态。这篇讲我怎么用一个不到 70 行的断点系统接住这三种形态,以及哪些账到现在还没还完。

二、断点系统本体:70 行接住三种形态

适配的核心是BreakpointSystem.ets(common/utils/ 下),基于 ArkUI 的 mediaquery 能力:

staticregister(uiContext:UIContext):void{BreakpointSystem.unregister()constmediaQuery=uiContext.getMediaQuery()BreakpointSystem.smListener=mediaQuery.matchMediaSync('(width<=600vp)')BreakpointSystem.mdListener=mediaQuery.matchMediaSync('(600vp<width<=840vp)')BreakpointSystem.lgListener=mediaQuery.matchMediaSync('(840vp<width)')// ……change 回调里 AppStorage.setOrCreate('currentBreakpoint', bp)}

三个设计决定,各有理由:

单点分发。三个 listener 的 change 回调都只做一件事:把断点写进 AppStorage 的currentBreakpoint。所有页面通过@StorageLink('currentBreakpoint')订阅,没有任何页面自己监听媒体查询。好处是断点逻辑只有一处,坏处是所有页面都被一个字符串驱动——这是下文魔法数问题的根源。

先注销再注册。register 开头先调 unregister,逐个 off 掉旧 listener 再建新的。这行防御来自一个真实的担忧:Entry 页面的 aboutToAppear 在热重载和窗口重建时可能被多次触发,listener 泄漏会让 change 回调叠加执行。

初始断点用 if 链兜底。listener 注册完后立刻探测一次当前态(sm.matches → md.matches → 否则 lg),保证首帧就有正确断点,不依赖第一次窗口变化事件才收敛。

三、四处消费点与一个魔法数问题

页面侧的消费方式统一是 @StorageLink 加 if 链。四个真实消费点:

  • Index.etsgetContentMaxWidth():lg→1180、md→960、sm→100000(等于不限制)
  • HomePage.etsgetBannerHeight():lg→260、md→220、sm→Sizes.BANNER_HEIGHT
  • CategoryPage:网格列数和间距随断点变化
  • ReadingPage:朗读页排版宽度

跑起来都正常,但写专栏复盘的时候我盯着这四处 if 链看出了问题:断点阈值 600/840 只存在于 BreakpointSystem 里,而每个消费点的数值(1180、960、260、220)散落在各自的 if 链里。想新增一个 xl 断点,或者把 840 调成 900,要改 N 个文件,漏一处就是某个页面在大屏上比例失调。最初做适配时只想着"让平板不丑",真正回头看才发现:阈值和数值分家,才是维护成本的开端。

解法很朴素——断点决策收敛成一张常量表:

exportclassBreakpointPolicy{staticreadonlyCONTENT_MAX_WIDTH:Record<string,number>={'sm':Number.MAX_SAFE_INTEGER,'md':960,'lg':1180}staticreadonlyBANNER_HEIGHT:Record<string,number>={'sm':180,'md':220,'lg':260}}

页面只读表不写分支。这个改造还没落地,是我给自己排的下一步——专栏连载里也公开记了这笔账。

四、两笔还没还的账

诚实说,当前 1.0.5 的适配是"骨架完整、细节欠账"。

账一:2in1 的自由窗口没有约束。module.json5 里没有配置 supportWindow 相关的窗口尺寸限制,2in1 上用户可以把窗口拉到很扁——断点会掉回 sm,内容宽度不限制,banner 压到 180。能用,但不好看。窗口最小尺寸约束是接下来要补的配置。

账二:折叠屏展开态只当大屏处理。当前实现里折叠屏展开就是 lg,没有用 display 的折叠状态 API(foldStatus)做展开态专属布局。菜谱场景其实有明确的机会:展开态是"左边步骤、右边计时器"的天然双栏场景。这是 1.0.6 的候选特性。

两笔账的优先级我按"用户感知频率"排:自由窗口约束影响所有 2in1 用户的每一次使用,先还;折叠屏双栏是增量体验,后还。

五、给同样要适配三种设备的你四条原则

  1. 声明 deviceTypes 之前先想清楚适配范围——声明了就要负责,少声明一个设备比多声明后适配烂更体面。
  2. 断点阈值只允许存在一处,消费点全部读表;魔法数散落是适配烂掉的开始。
  3. mediaquery 手写方案和 GridRow/GridCol 声明式方案二选一即可:页面少、断点行为独特(如 banner 高度)选手写;网格类页面用 GridRow 更省。
  4. 适配不是一次性的,每个版本迭代把"新页面是否处理了 md/lg"加进发布检查清单——我的 release-notes 里已经有这一项。

适配的尽头不是"每个设备都好看",而是"用户换设备时体验不断":手机上收藏的菜谱,到平板上还在收藏夹里;2in1 上拉窄窗口,断点平滑降级回手机布局。做到这一步,三种设备才真正是一个应用,而不是三个移植版本。

参考资料

  • HarmonyOS 应用自适应布局开发指导(断点)
  • ArkUI 媒体查询(mediaquery)文档
  • 工程源码:BreakpointSystem.ets、Index.ets、HomePage.ets、CategoryPage.ets、ReadingPage.ets

#鸿蒙 #HarmonyOS 7(API 26)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/28 1:56:24

377.组合总和 Ⅳ(背包)

链接&#xff1a;377. 组合总和 Ⅳ - 力扣&#xff08;LeetCode&#xff09; 题解&#xff1a; 组合总和 IV dp[i] 目标位i的组合组数是多少 dp[i] dp[i-A0] dp[i-A[1]] .. dp[1-A[n-1]]&#xff0c;枚举所有最后一个数字的可能 class Solution { public:int combination…

作者头像 李华
网站建设 2026/10/28 1:55:33

基于多星座导航信号模拟器的导航大模型端到端定位算法验证方法

摘 要&#xff1a;面向自动驾驶、无人机等安全关键场景&#xff0c;基于深度学习、大模型架构的GNSS智能接收机逐步用于城市遮挡、多径、欺骗等恶劣环境下的定位解算。野外实测方式难以获取带精准真值、参数可控的遮挡与欺骗样本&#xff0c;且场景复现与变量隔离难度高&#…

作者头像 李华
网站建设 2026/10/28 1:53:59

什么是四线制测试?为什么电池测试经常使用四线制?

四线制是电池测试中非常重要的一个概念。尤其是涉及低电阻、精密电压测量或者较大电流测试时&#xff0c;经常会看到它。一、两线制有什么问题&#xff1f;假设我们用两根线连接测试设备和电池。这两根线既负责传输电流&#xff0c;又负责测量电压。问题就来了&#xff1a;线缆…

作者头像 李华
网站建设 2026/10/28 1:53:58

aiopsterm 插件开发

aiopsterm 插件开发aiopsterm 插件是宿主可验证、可安装的声明式能力包&#xff0c;不执行插件自带的 JavaScript 入口。当前支持两类插件&#xff1a;content&#xff1a;向终端工作区贡献可见命令。provider&#xff1a;向宿主贡献受控的数据导入表单&#xff0c;由宿主适配器…

作者头像 李华
网站建设 2026/10/28 1:53:45

汽车电气系统深度科普!

搁二三十年前&#xff0c;车上那点电气系统说白了就是"三大件"&#xff1a;大灯、喇叭、点火线圈。掰着手指头都能数过来&#xff0c;出了问题也好找&#xff0c;顺着线捋就行。现在可完全不是那回事了。中控大屏、电动座椅、自动空调、全景天窗、座椅加热通风、各种…

作者头像 李华
网站建设 2026/10/28 1:53:14

提示缓存(Prompt Caching)是如何工作的?

提示缓存&#xff08;Prompt Caching&#xff09;是一种技术&#xff1a;模型把 prompt 中重复出现的那部分已经算过的工作保存下来&#xff0c;下次直接复用这份保存的结果&#xff0c;而不必从头再算一遍。 本文我们来讲清楚提示缓存是怎么工作的。我们还会看到为什么需要它、…

作者头像 李华