本文是「平行视界」系列第二篇(首篇见《HarmonyOS 7 平行视界 EasyGo 实战》)。基于 HarmonyOS 7(API 26)官方《平行视界》能力介绍与开发指导整理。文中代码是为说明问题自写的完整示例,不是官方示例的搬运;配置文件字段名、枚举值等事实性信息均标注官方出处,未能逐字核实的指向写法已注明"以官方文档为准";涉及真机表现的部分以真机实测为准,未做任何实测数据编造。


HarmonyOS 7 平行视界进阶实战:配置写好了为什么崩

引子:easy_go.json 写完了,真机一展开全是问题

V哥上期把平行视界的配置讲透了——一份 easy_go.json、homePage 配 navBar、mode 切购物/导航、ratio 配 1:2。评论区有位兄弟照抄跑通了,隔了两天回来留言:“V哥,配置我一字不差抄的,模拟器美如画,真机一展开,列表页跑到右边去了,详情页直接被截断,分屏入口点了没反应。”

这不是个例。V哥自己的电商 Demo 也踩过一模一样的坑。配置写对只是第一步,平行视界真正的坑在"配完之后":homePage 识别、UI 截断、一屏三区、和自由多窗的边界,这四个地方有一处没想清楚,真机展开就是翻车现场。

这期V哥把它拆开讲:上期讲"怎么配",这期讲"配完为什么崩",最后给一张"平行视界 / 自由多窗 / 自写 Navigation"的选型决策图。


一、homePage 识别失败:左右关系整个反了

上期V哥就强调过,homePage 必须主动配。这里把"不配会怎样"讲透。

官方在能力介绍里原话:默认的主页识别机制"在有些场景下不能准确识别"。什么场景会失准?典型两类:

  • 你的 Navigation 首页不是 navBar,而是某个 NavDestination 用 NavPathStack 直接当首页推的;
  • 冷启动走 relatedPage 进了二级页,路由栈初始态和系统认定"主页"对不上。

识别错了的后果很直观:系统以为右边那页是主页,把列表塞进右侧、详情挤到左侧,左右关系整个反掉。模拟器因为窗口尺寸固定、路由栈干净,往往看不出来;真机折叠展开、分屏、多实例这些时序一搅,就暴露了。

V哥的硬规则:homePage 永远显式配。Navigation 首页就是 "navBar";想让某个 NavDestination 当主页,就配它的 name。不要赌默认识别。

{
  "common": {
    "displayModeOptions": {
      "navigationSplitOptions": {
        // V哥注:首页必须显式声明,不赌默认识别
        "homePage": "navBar",          // 或配某个 NavDestination 的 name
        "relatedPage": "CategoryPage", // 冷启动直接进列表,缩短首屏路径
        "mode": 0
      }
    }
  }
}

二、UI 截断:窗口一半宽度装原布局,元素必溢出

这是官方"常见问题"第一条,也是真机翻车率最高的一处。平行视界把原来整屏的布局塞进"右半页",窗口宽度直接砍半,你按整屏写的固定宽度元素、绝对定位、硬编码边距,全溢出。

V哥给三板斧,按优先级来:

① 自适应布局优先(治本)。 用栅格、百分比、折行容器重写右页布局,让它能随容器宽自适应。这是唯一不依赖开关的方案。

② 虚拟容器兜底(性价比最高)。enableReducedContainerSize: true——断点、lpx、窗口宽度全部按"右侧页面尺寸"重新计算,相当于让系统把右页当成一个独立小窗口。官方还配套 drawableRectHook,让 Window.drawableRect 也按右页尺寸算,避免你拿到的窗口矩形还是整屏大。

③ 监听接口留给精细场景。 onNavDestinationSizeChange()、组件级的 on('navDestinationUpdate')(API 23+)能拿到页面真实尺寸,做动态字号、条件显隐。

// GoodsDetailPage.ets —— 拿右页真实尺寸,精细适配
import { window } from '@kit.ArkUI';

aboutToAppear(): void {
  // V哥注:enableReducedContainerSize 开启后,这里拿到的尺寸已是右页尺寸
  window.getLastWindow(getContext(this)).then((w) => {
    w.on('windowSizeChange', (size) => {
      // size.width 是右页真实宽度,据此切换布局密度
      this.adaptByWidth(size.width);
    });
  });
}

另外两类页面要单独标记:fullScreenPages 配置图片浏览、视频播放这类"进页退分栏、返回恢复"的页面;临时编辑页用 transPages 固定右侧不被推挤。这两个字段配错,要么全屏页被卡在分栏里,要么编辑页跟着被推走。


三、一屏三区:应用内分屏不是"点了就灵"

上期提过,配置 enableInSplitScreen: true 后,详情页顶部出分屏入口,应用以主窗口形式进系统窗口分屏,且原窗口继续保持平行视界。听着很美,真机有三个坑V哥必须提醒:

坑 1:入口可见性没判断对。 按钮要在"处于分栏态 且 还没分屏"时才露。用 getUIContext().isEasySplit() 判分栏态,windowStatusType 判是否已分屏,两个条件缺一不可——只判一个,要么不该露时露了,要么分屏后还露着。

坑 2:应用得支持多实例。 应用内分屏本质是再拉起一个 EntryAbility 实例。你的 Ability 没在 module.json5 里声明多实例支持,点了没反应,不报错但就是不开。

坑 3:主窗口占比有讲究。 SplitRatioPreference.PRIMARY_DOMINANT 让主窗口占主导,但左列表+详情已经占了一屏三区里的两区,再开的分屏别抢太多,否则三区挤成两区半。

// 分屏入口:分栏态 + 未分屏时露出
Button($r('app.string.enter_split'))
  .visibility(
    this.getUIContext().isEasySplit() &&
    this.mainWindowInfo.windowStatusType !== window.WindowStatusType.SPLIT_SCREEN
      ? Visibility.Visible : Visibility.None)
  .onClick(() => this.startSplitScreen())

private startSplitScreen(): void {
  const ctx = this.getUIContext().getHostContext() as common.UIAbilityContext;
  ctx.startAbility(
    { bundleName: 'com.vge.demo', abilityName: 'EntryAbility' },
    { windowMode: AbilityConstant.WindowMode.WINDOW_MODE_SPLIT_PRIMARY,
      splitRatio: window.SplitRatioPreference.PRIMARY_DOMINANT });
}

接口名(isEasySplit()WindowStatusType.SPLIT_SCREENWINDOW_MODE_SPLIT_PRIMARYSplitRatioPreference)均出自官方开发指导示例代码,实际分屏表现以真机实测为准。


四、边界:自由多窗模式下,平行视界不生效

这是最容易被忽略的一条硬边界。官方在 tablet 配置项里明确:自由多窗模式下,暂不支持平行视界

什么意思?用户在系统里把你的应用拖成自由窗口(自由缩放、悬浮),这个状态下平行视界那套左右分栏是不触发的,应用回退到单页。所以做窗口化、悬浮场景的业务,要先确认自己的主战场是不是自由多窗——是的话,平行视界那套配置等于没装。

那三种"大屏多任务"方案到底怎么选?V哥画了一张边界图(见配图),翻译成大白话:

  • 平行视界:系统级兜底,配置接入,能力受限。适合"左点右出"的路由栈场景(电商、IM、邮箱),一份 JSON 接住,不重写业务。
  • 自由多窗:用户主动拖拽缩放、多应用同屏,应用声明支持后由系统调度。适合需要和应用外内容并排、窗口尺寸不固定的场景。
  • 自写 Navigation 一多:主动适配,控制灵活,功能完整。适合要侧边栏、三分栏、跨栏联动、复杂转场的精细化设计。

三者不互斥:平行视界在手机投宽屏/折叠屏上兜底,Navigation 一多在你精雕细琢的主战场发力,自由多窗交给系统让用户自己拖——分层用,别互相打架。


五、V哥的真机验收清单

配置写完别急着合并,V哥列一份真机验收清单,按这个跑一遍:

  1. 折叠展开、窗口分屏、多实例三种时序各跑一遍,homePage 左右关系不能反;
  2. 右页把最长列表、最宽表格、绝对定位组件全点一遍,无截断无溢出;
  3. 深色模式、横竖屏各看一遍,分割线颜色深浅色都配了;
  4. 分屏入口在分栏态露出、分屏后隐藏,点了能开且主窗口保持平行视界;
  5. 自由多窗态下确认你的设计意图(是退回单页还是另有预案)。

真机表现千变万化,以真机实测为准;7.0 新能力需升级至 HarmonyOS 7 并以实际支持机型为准。


参考与出处

本文涉及的机制、字段与交互规则来自以下官方材料,均为V哥动笔前逐条核验的原文出处:


最后一句:平行视界的优雅在于"不写代码就能分屏",但它的坑也恰恰藏在"不写代码"的盲区里——homePage 别赌默认、截断先开虚拟容器、分屏先开多实例、自由多窗下承认它不生效,把这四个盲区填平,折叠屏展开的那一秒,你的应用才真正站得稳。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐