资讯动态

平行视界和 Navigation Split 有什么不同?用同一个 Demo 看两种分栏思路【鸿蒙心迹】

发布时间:2026/10/14 21:06:37 来源:尧图企业网站定制
你好欢迎来到我的博客我是【菜鸟学鸿蒙】我是一名在路上的移动端开发者正从传统“小码农”转向鸿蒙原生开发的进阶之旅。为了把学习过的知识沉淀下来也为了和更多同路人互相启发我决定把探索 HarmonyOS 的过程都记录在这里。️主要方向ArkTS 语言基础、HarmonyOS 原生应用Stage 模型、UIAbility/ServiceAbility、分布式能力与软总线、元服务/卡片、应用签名与上架、性能与内存优化、项目实战以及 Android → 鸿蒙的迁移踩坑与复盘。内容节奏从基础到实战——小示例拆解框架认知、专项优化手记、实战项目拆包、面试题思考与复盘让每篇都有可落地的代码与方法论。 我相信写作是把知识内化的过程分享是让生态更繁荣的方式。如果你也想拥抱鸿蒙、热爱成长欢迎关注我一起交流进步前言同样是把一个应用拆成左右两栏平行视界和 Navigation 的 Split 模式在表现上非常相似——都能在折叠屏展开态呈现左列表 右详情的布局效果。但这两种方案的出发点、控制权归属和适用边界其实相差很远。本文用同一个列表详情场景分别用两种方式实现对比它们在路由结构、窗口适配和业务条件上的差异帮助你在选型时有一个更清晰的判断依据。一、为什么两者看起来很像视觉上的相似来自于一个共同目标在宽屏下更充分地利用横向空间。折叠屏展开态或平板横屏时屏幕宽度通常超过 800vp单页全屏显示会让内容显得稀疏左侧展示列表、右侧展示详情几乎是这类设备上最自然的布局形式。Navigation Split 和平行视界都可以实现这个效果所以容易被认为是同一类东西。真正的区别在于谁负责把屏幕分成两半谁负责决定两半里分别显示什么。Navigation Split开发者在应用层自己设计分栏组件的显示模式、宽度比例、路由关系都由应用代码控制。平行视界分屏这件事由系统完成开发者的主要工作是声明我支持平行视界以及保证自己的布局在窗口尺寸减半时还能正常工作。这个控制权的差别决定了两者适用的场景和需要处理的问题完全不同。二、Navigation 分栏是什么Navigation 是 ArkUI 提供的导航容器组件从 API Version 8 开始支持从 API Version 11 起推荐使用Navigation NavDestination NavPathStack的组合方式管理路由。Navigation 通过.navigationMode()属性控制显示模式共有三种模式说明NavigationMode.Stack单栏堆栈同时只显示一个页面NavigationMode.SplitNavBar主栏和 NavDestination内容栏并排显示NavigationMode.Auto宽度 ≥ 600vp 时自动切换 Split 600vp 时切换 StackSplit 模式下Navigation 内部会渲染两个区域左侧是 NavBar主栏始终可见右侧是 NavDestination内容区显示路由栈顶的页面。这个分栏完全在应用内部完成不依赖折叠屏也不需要系统介入。Auto 模式是实际项目里更常用的选择它可以让同一套代码在手机竖屏Stack和折叠屏展开态/平板横屏Split下分别呈现合适的交互形态。三、平行视界解决什么问题平行视界Parallel View是 HarmonyOS 面向折叠屏展开态设计的系统级能力其定义来自官方文档中的表述在折叠屏展开态下系统将同一个应用的两个页面同时显示在屏幕左右两侧。几个关键特点值得单独说明1. 系统级不是应用级分屏的窗口管理由系统完成。应用实际持有的是一个完整窗口但该窗口的尺寸在平行视界激活后变为整屏宽度的约一半。开发者不需要也无法直接管理左半屏和右半屏两个独立窗口。2. 同进程、同应用实例平行视界不是分屏多任务两个区域属于同一个应用进程数据状态可以直接共享不需要跨进程通信。3. 折叠屏专属官方文档明确平行视界仅适用于折叠屏手机和折叠屏平板且仅在展开态下生效。折叠时应用自动回退为单页面显示。4. 需要开发者声明应用需要在module.json5中声明支持平行视界系统才会在满足条件时提供入口。声明本身不代表平行视界一定会触发触发逻辑由系统决定。四、用同一个列表详情案例分别设计场景描述一个新闻列表应用左侧显示文章标题列表点击后右侧显示文章正文详情。方案 A用 Navigation Split 实现这是一个纯应用层方案核心在于 Navigation 组件的配置和 NavPathStack 的管理。页面结构├── pages/ │ └── Index.ets // 包含 Navigation 组件承载主栏列表 ├── components/ │ ├── ArticleList.ets // 列表组件放在 Navigation NavBar 区域 │ └── ArticleDetail.ets // 详情组件作为 NavDestinationIndex.etsNavigation 组件配置import{NavPathStack}fromkit.ArkUI;// 路由注册将 NavDestination 对应的组件与路由名称绑定BuilderfunctionpageMap(name:string,param:ESObject){if(nameArticleDetail){ArticleDetail()}}EntryComponentstruct Index{// 创建路由栈通过 Provide 向子组件共享Provide(pathStack)pathStack:NavPathStacknewNavPathStack();build(){Navigation(this.pathStack){// NavBar 区域主栏内容ArticleList()}.navDestination(pageMap)// Auto 模式宽屏自动分栏窄屏自动单栏.navigationMode(NavigationMode.Auto)// 主栏宽度仅 Split 模式下生效.navBarWidth(40%).width(100%).height(100%)}}ArticleList.ets列表组件触发路由跳转Componentstruct ArticleList{// 消费上层提供的路由栈Consume(pathStack)pathStack:NavPathStack;privatearticles:string[][文章一,文章二,文章三];build(){List(){ForEach(this.articles,(item:string){ListItem(){Text(item).width(100%).padding(16).onClick((){// 按名称压栈触发右侧 NavDestination 显示this.pathStack.pushPathByName(ArticleDetail,{title:item});})}})}}}ArticleDetail.ets详情页作为 NavDestinationComponentstruct ArticleDetail{// 通过 NavDestination 的 onReady 回调获取路由参数Statetitle:string;build(){NavDestination(){Column(){Text(this.title).fontSize(20).padding(24)}.width(100%).height(100%)}.onReady((ctx:NavDestinationContext){// 获取压栈时传入的参数constparamctx.pathInfo.paramasRecordstring,string;this.titleparam?.title??;})}}这段代码真正需要关注的是三个地方第一NavigationMode.Auto让分栏时机由组件根据窗口宽度自动决定不需要手动监听折叠状态第二路由栈通过Provide/Consume跨组件传递列表组件无需持有 Navigation 引用第三详情页通过NavDestinationContext拿参数而不是依赖全局状态。方案 B用平行视界实现同一场景平行视界方案的核心工作不在 UI 组件层而在声明 布局响应。步骤一module.json5 声明支持平行视界{module:{abilities:[{name:EntryAbility,srcEntry:./ets/entryability/EntryAbility.ets,metadata:[{name:ohos.extension.parallelview,value:true}]}]}}这一步是告诉系统这个应用支持平行视界系统才会在折叠屏展开时向用户提供入口。这里容易有一个理解偏差加了这个声明不等于应用一定会进入平行视界最终触发与否由系统决定。步骤二监听窗口尺寸变化响应分屏状态平行视界激活后应用窗口的实际宽度会变为原来的约一半。应用不会收到平行视界已激活这样的专项通知而是通过窗口尺寸变化来感知状态变化。import{window}fromkit.ArkUI;// 在 EntryAbility 的 onWindowStageCreate 中注册监听onWindowStageCreate(windowStage:window.WindowStage):void{windowStage.getMainWindow((err,windowObj){if(err.code!0){return;}windowObj.on(windowSizeChange,(size:window.Size){// size.width 单位为 px需要转换为 vp 再用于布局判断constwidthVppx2vp(size.width);// 根据 widthVp 动态调整 AppStorage 或全局状态通知页面更新布局AppStorage.setOrCreate(windowWidthVp,widthVp);});});}步骤三页面层根据窗口宽度自适应布局平行视界激活后每个分屏区域的宽度约为整屏宽度的一半通常在手机折叠屏展开时对应 sm 或 md 断点320vp–840vp 区间。页面层的布局需要保证在这个宽度下依然可用。EntryComponentstruct ArticleListPage{StorageProp(windowWidthVp)windowWidthVp:number360;build(){// 根据窗口宽度选择布局策略// 平行视界下宽度约为整屏一半这里的逻辑与普通响应式布局一致Column(){List(){// 列表内容}.width(100%)}.width(100%).height(100%)}}这里真正需要关注的是页面本身不需要知道自己是否处于平行视界它只需要响应窗口宽度变化。这与普通响应式布局的开发方式是一致的平行视界适配的主要工作是保证布局在宽度减半后不出问题而不是增加专门的平行视界分支逻辑。五、路由结构区别两种方案在路由层面的差别比表面看起来更根本。Navigation Split 的路由是应用内路由分栏里的左侧和右侧是 Navigation 组件内部的 NavBar 区域和 NavDestination 区域。它们由同一个 NavPathStack 管理路由跳转如pushPathByName决定右侧显示什么内容。这意味着路由栈的状态完全在应用层可控返回操作pop()可以精确控制在分栏模式下NavBar 始终可见不受路由栈影响路由深度、页面参数传递、拦截逻辑都由开发者自己设计平行视界的分屏是系统管理的平行视界下系统将应用窗口分成两半每一半展示应用当前的某个页面状态。官方文档建议配合 Navigation NavPathStack 使用可以让平行视界与路由系统更自然地协同工作——但路由本身是 Navigation 的职责不是平行视界直接提供的能力。换句话说平行视界不提供路由 API它只管窗口怎么分分出来的区域里显示什么还是由应用的路由逻辑决定。维度Navigation Split平行视界路由控制者应用NavPathStack应用路由逻辑不变分栏控制者应用组件属性系统路由 APIpushPathByName、pop等无专属路由 API分栏时机开发者通过 navigationMode 控制系统在满足条件时触发六、窗口适配思路区别Navigation Split 不需要主动处理窗口尺寸在 Auto 模式下Navigation 组件本身会根据当前容器宽度自动在 Stack 和 Split 之间切换默认阈值是 600vp。开发者不需要监听窗口尺寸或折叠状态只需要保证 NavBar 内容和 NavDestination 内容在不同宽度下都能正常显示。如果需要调整触发阈值可以通过minContentWidthAPI Version 12属性修改。平行视界必须主动响应窗口尺寸变化平行视界激活后窗口宽度会发生变化这是应用感知平行视界状态的唯一途径。如果不监听窗口尺寸变化页面布局可能在分屏后显示异常例如仍然按全屏宽度渲染导致内容溢出或排版错乱。官方文档明确说明不应使用display.getDefaultDisplaySync()获取全屏宽度作为布局依据应优先使用窗口宽度。这一点在平行视界场景下尤为重要因为平行视界下窗口宽度和屏幕宽度不再相等。七、各自需要考虑的业务条件在动手选型之前有几个业务条件值得先确认清楚。使用 Navigation Split 时需要考虑NavBar 始终可见这件事是否符合业务Split 模式下NavBar 无论路由栈深度如何变化始终保持可见。如果业务上需要某个状态下完全隐藏左栏需要使用.hideNavBar(true)属性。右侧内容区的初始状态路由栈为空时右侧内容区默认为空白需要设计一个占位界面否则用户体验会比较差。断点设计如果使用 Auto 模式要确认 600vp 这个默认阈值是否适合自己的布局必要时用minContentWidth调整。使用平行视界时需要考虑设备范围如果应用需要支持普通直板手机、平板等非折叠屏设备平行视界在这些设备上不会生效布局适配不能依赖平行视界触发。不能假设平行视界一定会激活即使声明了支持用户也可能不开启平行视界或设备不处于展开态。布局需要在没有平行视界时也能正常工作。响应式布局是前提平行视界的本质是窗口尺寸变化如果应用本身就有良好的响应式布局适配成本会低很多如果有大量固定宽度的代码这些地方在分屏后容易出问题。八、如何根据官方能力边界选择官方文档对两者的定位有明确的说明Navigation Split 是应用内布局方案平行视界是系统级分屏机制。两者不是互相替代的关系能力边界不同适用的场景自然也不同。按照官方能力边界可以用以下条件做判断优先考虑 Navigation Split 的场景应用需要在手机、平板、折叠屏等多种设备上都支持主从布局需要对分栏时机、宽度比例、路由逻辑有精确控制应用不依赖特定设备形态要求较强的跨设备一致性优先考虑平行视界的场景应用的主要用户群体使用折叠屏希望充分利用折叠屏展开态的大屏空间应用已有良好的响应式布局基础希望以较低成本支持折叠屏分屏体验产品希望向用户提供同一应用双页面并排的交互形态且愿意由系统来管理分屏行为两者也可以同时使用。在平行视界激活后每个分屏区域内部仍然可以使用 Navigation 管理路由官方文档也建议将 Navigation NavPathStack 作为平行视界场景下的路由管理方案。开发经验总结控制权归属是核心差异Navigation Split 把分栏控制权交给开发者平行视界把窗口管理权交给系统。这个差异决定了两者的开发思路完全不同。平行视界的适配本质是响应式布局不要把平行视界的适配理解为写一套平行视界专用代码它的适配工作主要是保证布局在窗口尺寸变化时能正常响应。NavigationMode.Auto 是常见的实用选择对于需要同时支持多种设备形态的应用Auto 模式可以用同一套代码处理单栏和分栏场景不需要开发者手动判断设备类型。不要用屏幕宽度替代窗口宽度这个问题在平行视界场景下特别容易出现display.getDefaultDisplaySync()返回的是整屏尺寸平行视界激活后它依然是整屏的值用它做布局判断会得到错误的结果。两者可以叠加使用折叠屏展开态下平行视界管窗口分屏Navigation 管应用内路由互不冲突官方文档也推荐这种组合方式。如果你正在同时做多设备适配可以重点检查一下自己的布局代码里是否有依赖屏幕宽度而非窗口宽度做判断的地方——这类问题在普通设备上不会暴露但在平行视界激活后很容易导致布局异常往往比显式的分栏逻辑更难排查。 写在最后如果你觉得这篇文章对你有帮助或者有任何想法、建议欢迎在评论区留言交流你的每一个点赞 、收藏 ⭐、关注 ❤️都是我持续更新的最大动力我是一个在代码世界里不断摸索的小码农愿我们都能在成长的路上越走越远越学越强感谢你的阅读我们下篇文章再见✍️ 作者菜鸟不学编程 本文原创转载请注明出处。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑