HarmonyOS APP《画伴梦工厂》开发第63篇-平行视界EasyGo与应用内分屏
第7.13篇:平行视界 EasyGo 与应用内分屏
难度:⭐⭐ 进阶
前置知识:第 5.7 篇 多设备形态适配
涉及源文件:参考 UI Design Kit 文档
概述
在 HarmonyOS 7(API 26)中,多窗口交互体系迎来了两项重要能力:平行视界 EasyGo 和应用内分屏(In-App Split Screen)。前者是系统级的应用分屏启动框架,后者是应用开发者可控的页面级分屏 API。两者共同构成了鸿蒙在大屏设备上的"高效多任务"技术底座。
对于"画伴梦工厂"这样的创作类应用而言,这些能力尤为重要——用户可能需要在画布上绘画的同时查看参考图、在编辑作品时对比前后版本、或者在 AI 生成等待期间浏览其他内容。传统的全屏页面切换模式在这些场景下效率低下,而平行视界 EasyGo 与应用内分屏则提供了全新的交互维度。
本文将系统性地解析这两项能力的设计理念、API 模型、配置方式,并结合"画伴梦工厂"的创作场景探讨其落地路径。
一、平行视界 EasyGo——应用级分屏启动框架
1.1 什么是平行视界 EasyGo?
平行视界(Parallel Vision)是 HarmonyOS 在大屏设备(平板、折叠屏、2in1)上的分屏交互体系。其核心思想是:同一个应用可以在屏幕上同时展示两个页面,左边是总览/导航,右边是详情/内容。
在 HarmonyOS 7 之前,平行视界更多是系统级的自动适配行为——应用无需做任何配置,系统在横屏下自动将页面拆分为左右两栏。但这种"一刀切"的方式存在明显局限:
- 应用无法控制分屏的比例和模式
- 无法选择哪些页面可以并排显示
- 无法在分屏中嵌入自定义交互
EasyGo 正是为了解决这些问题而生的。它是平行视界在 HarmonyOS 7 中的升级版本,提供了一组声明式配置 API,让应用开发者能够精确控制分屏的启动方式、显示比例、交互模式。
1.2 EasyGo 的核心能力
| 能力 | 说明 | 适用场景 |
|---|---|---|
| 1:2 启动 | 左侧 1/3、右侧 2/3 的分屏比例 | 列表+详情模式 |
| 2:1 启动 | 左侧 2/3、右侧 1/3 的分屏比例 | 主画布+辅助面板模式 |
| 购物模式 | 左右联动滚动,商品列表与详情同屏显示 | 电商价格对比 |
| 导航模式 | 左侧地图总览、右侧路线详情 | 导航场景 |
| 配置式接入 | 通过 JSON 或代码声明分屏行为 | 所有场景 |
1.3 EasyGo 四种模式详解
1:2 比例模式
这是最常用的分屏比例,适用于"总览 + 详情"的场景:
┌──────────┬──────────────────────────┐
│ │ │
│ 列表 │ 详情 │
│ 1/3 │ 2/3 │
│ │ │
└──────────┴──────────────────────────┘
// 启动一个 1:2 比例的平行视界
// 左侧 pages/ItemList,右侧 pages/ItemDetail
import { parallelVision } from '@kit.KernelKit';
parallelVision.startEasyGo({
leftPage: 'pages/ItemList',
rightPage: 'pages/ItemDetail',
ratio: '1:2', // 左右比例
linkType: 'detail', // 联动类型:列表→详情
params: {
categoryId: 'all',
fromEasyGo: true // 标记来自 EasyGo,便于页面做适配
}
});
2:1 比例模式
当主操作区域需要更大空间时使用,适用于"主画布 + 辅助面板"场景:
┌──────────────────────┬──────────┐
│ │ │
│ 主操作区 │ 辅助面板 │
│ 2/3 │ 1/3 │
│ │ │
└──────────────────────┴──────────┘
// 启动 2:1 比例的 EasyGo,适用于创作工具
parallelVision.startEasyGo({
leftPage: 'pages/CanvasEditor', // 画布编辑区
rightPage: 'pages/ToolPalette', // 工具面板(调色板、笔刷)
ratio: '2:1',
linkType: 'tool', // 工具面板联动
params: { canvasId: 'current' }
});
购物模式
购物模式是 EasyGo 针对电商场景专门优化的变体:
// 购物模式——左右联动,沉浸式比价
parallelVision.startEasyGo({
leftPage: 'pages/ProductList', // 商品列表(左)
rightPage: 'pages/ProductDetail', // 商品详情(右)
mode: 'shopping', // 购物模式
linkConfig: {
// 选中商品时右侧自动跳转到详情
autoSync: true,
// 右侧滚动时左侧高亮对应商品
highlightSync: true,
// 可同时对比多个商品
multiCompare: true
}
});
购物模式的核心特性是双向联动:用户在左侧选择商品时右侧自动更新详情;用户在右侧浏览详情时左侧自动高亮对应商品。这种联动使得比价变得非常高效。
导航模式
导航模式专为地图导航场景设计:
// 导航模式——地图总览 + 路线详情
parallelVision.startEasyGo({
leftPage: 'pages/MapOverview', // 地图总览
rightPage: 'pages/RouteDetail', // 路线详情
mode: 'navigation',
linkConfig: {
// 点击右侧路线时在地图上高亮
highlightOnMap: true,
// 地图缩放与右侧同步
zoomSync: true
}
});
二、EasyGo 与系统分屏的本质区别
很多开发者会问:EasyGo 分屏和系统级分屏(拖拽到屏幕边缘触发)有什么区别?答案是控制权的粒度不同。
2.1 系统分屏的局限
系统分屏是操作系统层面的能力,用户可以将任意两个应用左右并排显示。但它的控制权在用户手中——应用开发者无法干预分屏中显示的内容、比例、联动行为。
系统分屏的优点:
├── 用户可以自由组合任意应用
├── 不需要应用做任何适配
└── 比例由用户拖拽调节
系统分屏的局限:
├── 应用无法控制默认比例
├── 应用无法预置左右页面内容
├── 不支持页面间联动(如列表选中→详情更新)
└── 不能自定义交互模式
2.2 EasyGo 的开发者控制力
EasyGo 则提供了应用开发者主导的分屏控制能力:
| 控制维度 | 系统分屏 | EasyGo |
|---|---|---|
| 启动方 | 用户 | 应用代码或用户 |
| 默认比例 | 用户拖拽决定 | 开发者预设(1:2/2:1) |
| 左右页面内容 | 两个独立应用 | 同一应用内的两个页面 |
| 页面间联动 | 不支持 | 支持(通过 linkConfig) |
| 交互模式 | 通用 | 可定制(购物/导航等) |
| 参数传递 | 不支持 | 通过 params 传递 |
| 状态共享 | 不支持 | 通过 AppStorage 共享 |
2.3 选择指南
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 同一应用内两个页面的协同 | EasyGo | 支持页面间联动和数据共享 |
| 两个不同应用的并排使用 | 系统分屏 | 跨应用场景唯一选择 |
| 电商比价 | EasyGo 购物模式 | 内置双向联动,体验最优 |
| 画布+工具面板 | EasyGo 2:1 | 主操作区更大空间 |
| 多任务办公 | 系统分屏 | 需要不同应用协同 |
三、应用内分屏——API 26 的新能力
3.1 什么是应用内分屏?
如果说 EasyGo 是应用级的分屏框架(一个应用分在两个页面),那么应用内分屏(In-App Split Screen)就是页面级的分屏能力。它允许在同一个页面内部将屏幕分割为两个独立区域,每个区域运行独立的组件树。
3.2 核心 API
应用内分屏的核心 API 位于 @kit.ArkUI 中:
import { SplitScreen } from '@kit.ArkUI';
@Component
struct CreativeStudio {
build() {
SplitScreen({
// 分割方向
direction: 'horizontal', // 'horizontal' | 'vertical'
// 默认分割比例(百分比)
defaultRatio: 0.6, // 左侧/上方占 60%
// 最小比例
minRatio: 0.3,
// 最大比例
maxRatio: 0.7,
// 是否显示分割线
divider: true,
// 第一位子组件
primary: () => {
this.CanvasArea()
},
// 第二位子组件
secondary: () => {
this.PanelArea()
}
})
.width('100%')
.height('100%')
}
}
3.3 应用内分屏的特性
| 特性 | 说明 |
|---|---|
| 方向控制 | 支持水平分割(左右)和垂直分割(上下) |
| 比例调节 | 用户可拖拽分割线调整比例 |
| 比例限制 | 通过 minRatio/maxRatio 防止过度压缩某一侧 |
| 分割线定制 | 自定义分割线的颜色、宽度、样式 |
| 独立组件树 | 两侧组件拥有独立的生命周期和状态 |
3.4 与 EasyGo 的对比
| 维度 | EasyGo | 应用内分屏 |
|---|---|---|
| 层级 | 应用级(两个 Page) | 页面级(一个 Page 内) |
| 路由 | 两个独立路由栈 | 共享同一路由栈 |
| 状态共享 | 通过 AppStorage / 事件总线 | 通过 @State / @Link |
| 适用场景 | 列表+详情、购物比价 | 画布+工具面板、编辑器内分栏 |
| 配置方式 | 声明式配置 + 代码启动 | ArkUI 组件声明 |
四、配置式接入——声明式配置 EasyGo
EasyGo 最强大的特性之一是其配置式接入方式。应用可以通过 JSON 声明或代码声明两种方式定义 EasyGo 行为。
4.1 JSON 声明式配置
在 module.json5 或独立配置文件中声明 EasyGo 行为:
{
"easyGo": {
"enabled": true,
"defaultMode": "1:2",
"modes": [
{
"name": "shopping",
"ratio": "1:2",
"left": "pages/ProductList",
"right": "pages/ProductDetail",
"linkType": "detail"
},
{
"name": "canvas",
"ratio": "2:1",
"left": "pages/CanvasEditor",
"right": "pages/ToolPalette",
"linkType": "tool"
},
{
"name": "compare",
"ratio": "1:1",
"left": "pages/ArtworkViewer",
"right": "pages/ArtworkViewer",
"linkType": "compare",
"compareMode": true
}
],
"supportedOrientations": ["landscape", "portrait"],
"minScreenWidth": 600 // 仅在宽度 ≥ 600vp 时启用
}
}
这种配置方式的优势在于:
- 声明式:将 EasyGo 行为从代码中剥离,便于维护和调整
- 多模式支持:可以在配置中定义多种分屏模式,按需切换
- 条件启用:可以通过 minScreenWidth 等条件自动适配不同设备
4.2 代码声明式配置
除了 JSON 配置,也可以通过代码动态配置:
import { parallelVision, EasyGoConfig } from '@kit.KernelKit';
class AppEasyGoManager {
private config: EasyGoConfig = {
enabled: true,
defaultMode: '1:2',
modes: [
{
name: 'shopping',
ratio: '1:2',
left: 'pages/ProductList',
right: 'pages/ProductDetail',
linkType: 'detail'
}
],
minScreenWidth: BreakpointConfig.lg // 复用断点系统的 lg 阈值
};
// 在 Ability 的 onCreate 中初始化
initialize(context: UIAbilityContext) {
parallelVision.configure(this.config);
}
// 运行时切换模式
switchMode(modeName: string) {
parallelVision.switchMode(modeName);
}
// 动态注册新的分屏模式
registerMode(mode: EasyGoMode) {
parallelVision.registerMode(mode);
}
}
五、响应式布局的整合
EasyGo 与第 5 章讨论的响应式布局(BreakpointSystem + BreakPointType)天然契合。
5.1 根据断点决定是否启用 EasyGo
并不是所有设备都需要 EasyGo——手机竖屏(sm)下屏幕宽度有限,分屏反而会降低可用性。通过断点系统,可以精确控制 EasyGo 的启用条件:
// 根据当前断点决定是否启用 EasyGo
class EasyGoAwareComponent {
@StorageLink('currentBreakpoint') currentBreakpoint: string = 'sm';
get shouldEnableEasyGo(): boolean {
// 仅在 md 及以上断点启用 EasyGo
return !['sm'].includes(this.currentBreakpoint);
}
openInEasyGoIfNeeded(listPage: string, detailPage: string, params?: Object) {
if (this.shouldEnableEasyGo) {
parallelVision.startEasyGo({
leftPage: listPage,
rightPage: detailPage,
ratio: '1:2',
params: params || {}
});
} else {
// sm 断点下退化为普通页面跳转
this.getUIContext().getRouter().pushUrl({
url: detailPage,
params: params
});
}
}
}
5.2 分屏比例随断点调节
不同断点下,最优的分屏比例是不同的:
// 断点感知的分屏比例
const EASYGO_RATIO = new BreakPointType<string>({
sm: '1:1', // 小屏不使用 EasyGo,备用值
md: '2:1', // 中屏:主区域更大
lg: '1:2', // 大屏:详情区域更大
xl: '1:2' // 超大屏:详情区域更大,充分利用宽屏
});
// 分屏内容区域的布局本身也应是响应式的
function startResponsiveEasyGo(breakpoint: string) {
const ratio = EASYGO_RATIO.getValue(breakpoint);
parallelVision.startEasyGo({
// 根据断点选择不同的内容页面
leftPage: breakpoint === 'md' ? 'pages/CompactList' : 'pages/FullList',
rightPage: 'pages/ItemDetail',
ratio: ratio,
params: { breakpoint }
});
}
5.3 应用内分屏的响应式适配
应用内分屏同样需要与响应式布局整合。当设备为小屏时,分屏可能无法正常使用,此时需要降级为单栏布局:
@Component
struct AdaptiveCreativeStudio {
@StorageLink('currentBreakpoint') currentBreakpoint: string = 'sm';
build() {
Column() {
if (this.currentBreakpoint === 'sm') {
// 小屏:单栏,通过 Tab 切换画布和工具
this.SingleColumnLayout()
} else {
// 中屏及以上:分屏显示
SplitScreen({
direction: 'horizontal',
defaultRatio: 0.65,
minRatio: 0.4,
maxRatio: 0.8,
primary: () => this.CanvasArea(),
secondary: () => this.ToolPaletteArea()
})
}
}
.width('100%')
.height('100%')
}
}
六、典型用例:购物比价与辅助窗口
6.1 购物比价模式
购物比价是 EasyGo 最具代表性的场景之一。用户可以在一个应用中同时浏览商品列表和商品详情,无需反复切换页面。
交互流程:
用户在商品列表中浏览
│
▼
点击某商品 → 右侧自动打开详情
│
▼
用户在右侧浏览详情 →
左侧自动高亮当前商品
│
▼
用户点击"对比" →
左右并排显示两个商品详情
项目中的代码实现思路:
// 比价场景的 EasyGo 启动逻辑
function startPriceComparison(context: Context) {
parallelVision.startEasyGo({
leftPage: 'pages/PriceListPage',
rightPage: 'pages/ProductDetailPage',
mode: 'shopping',
ratio: '1:2',
linkConfig: {
autoSync: true, // 选中自动同步右侧详情
highlightSync: true, // 滚动时同步高亮
multiCompare: true, // 支持多商品对比
compareLimit: 4 // 最多同时对比 4 个商品
}
});
}
6.2 辅助窗口模式
辅助窗口模式是 EasyGo 的另一种重要应用形式——主应用在正常使用,辅助窗口提供额外的信息或工具支持。
┌──────────────────────┬────────────────┐
│ │ │
│ 主内容区 │ 辅助窗口 │
│ (全屏正常使用) │ (参考信息) │
│ │ │
│ │ │
└──────────────────────┴────────────────┘
辅助窗口的典型场景包括:
| 场景 | 主窗口 | 辅助窗口 |
|---|---|---|
| 写作 | 编辑器 | 参考笔记/资料 |
| 编程 | 代码编辑器 | 文档/API 参考 |
| 设计 | 设计稿 | 色板/素材库 |
| 绘画 | 画布 | 调色板/笔刷/参考图 |
七、在"画伴梦工厂"中应用——创作模式
7.1 创作模式的痛点
在"画伴梦工厂"的当前设计中,用户创作时需要在画布、调色板、笔刷选择器、参考图之间频繁切换。典型的交互路径是:
画布上绘画 → 关闭画布 → 打开调色板 → 调整颜色 → 返回画布
→ 画几笔 → 打开笔刷选择器 → 调整笔刷大小 → 返回画布
→ 画几笔 → 打开参考图 → 查看参考 → 返回画布
这种"打开-关闭-返回"的模态切换模式打断了创作流,尤其在大屏设备上,屏幕空间本应允许这些工具同时可见。
7.2 方案一:EasyGo 画布+工具侧栏
利用 EasyGo 的 2:1 模式,将画布和工具面板并排显示:
// 启动创作模式的 EasyGo
function startCreativeEasyGo(canvasId: string) {
parallelVision.startEasyGo({
leftPage: 'pages/CanvasEditor', // 左侧画布占 2/3
rightPage: 'pages/CreativeToolPanel', // 右侧工具面板占 1/3
ratio: '2:1',
mode: 'creation', // 自定义创作模式
linkConfig: {
// 画布上选中元素时,右侧自动显示该元素的属性
autoSync: true,
// 工具面板中调整参数时,画布实时预览
realtimePreview: true
},
params: {
canvasId: canvasId,
fromEasyGo: true // 标记,便于页面做适配
}
});
}
右侧工具面板的设计:
// CreativeToolPanel.ets
@Entry
@Component
struct CreativeToolPanel {
@State private selectedTool: string = 'brush';
@State private brushSize: number = 5;
@State private color: string = '#000000';
private canvasId: string = '';
aboutToAppear() {
const params = this.getUIContext().getRouter().getParams() as Record<string, Object>;
this.canvasId = params?.['canvasId'] as string || '';
// 监听来自画布的事件
this.getUIContext().getEventHub().on('elementSelected', (elementId: string) => {
// 当画布上选中元素时,自动加载其属性
this.loadElementProperties(elementId);
});
}
// 调整笔刷大小 → 通知画布实时更新
onBrushSizeChange(newSize: number) {
this.brushSize = newSize;
AppStorage.set('brushSize', newSize); // 通过 AppStorage 共享给画布
AppStorage.set('needsBrushUpdate', true); // 触发画布更新
}
build() {
Column() {
// 工具选择器
Row() {
this.ToolButton('brush', '画笔')
this.ToolButton('eraser', '橡皮')
this.ToolButton('fill', '填充')
this.ToolButton('picker', '取色')
}
.padding(12)
// 笔刷大小调节
Text('笔刷大小')
Slider({ value: this.brushSize, min: 1, max: 50 })
.onChange((v) => this.onBrushSizeChange(v))
// 调色板
Text('颜色选择')
ColorPicker({ selectedColor: this.color })
.onChange((c) => {
this.color = c;
AppStorage.set('currentColor', c);
})
// 参考图区域
Text('参考图')
Image(this.referenceImage)
.width('100%')
.height(120)
.objectFit(ImageFit.Contain)
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
}
7.3 方案二:应用内分屏的画布+参考图
另一种场景是用户在创作时需要参考另外一张图(比如参考实物照片来绘画)。使用应用内分屏可以实现画布和参考图的并排显示:
@Component
struct CanvasWithReference {
@State private splitRatio: number = 0.55;
build() {
SplitScreen({
direction: 'horizontal',
defaultRatio: this.splitRatio,
minRatio: 0.4,
maxRatio: 0.7,
primary: () => {
// 画布区域
Canvas(this.canvasContext)
.width('100%')
.height('100%')
.onTouch((event) => {
// 涂鸦逻辑
})
},
secondary: () => {
// 参考图区域
Column() {
Image($r('app.media.reference_photo'))
.width('100%')
.objectFit(ImageFit.Contain)
Text('双指缩放参考图')
.fontSize(12)
.opacity(0.5)
}
.padding(8)
.alignItems(HorizontalAlign.Center)
}
})
.width('100%')
.height('100%')
}
}
7.4 方案三:画布+画廊对比(前后版本对比)
创作过程中,用户常常需要对比当前版本和之前保存的版本:
// 通过 EasyGo 对比两个版本
function compareVersions(versionA: string, versionB: string) {
parallelVision.startEasyGo({
leftPage: 'pages/ArtworkViewer', // 左侧显示版本 A
rightPage: 'pages/ArtworkViewer', // 右侧显示版本 B
ratio: '1:1', // 1:1 等分屏幕
mode: 'compare', // 对比模式
params: {
leftImageId: versionA,
rightImageId: versionB,
compareMode: true // 开启对比模式
}
});
}
// ArtworkViewer.ets 中根据参数决定加载哪张图
aboutToAppear() {
const params = this.getUIContext().getRouter().getParams() as Record<string, Object>;
this.imageId = params?.['leftImageId'] || params?.['rightImageId'] || '';
this.isCompareMode = params?.['compareMode'] === true;
if (this.isCompareMode) {
// 对比模式下隐藏交互工具栏,专注于显示
this.showToolbar = false;
}
}
7.5 三种方案的选型
| 方案 | 分屏方式 | 适用场景 | 推荐度 |
|---|---|---|---|
| EasyGo 2:1 画布+工具 | 应用级分屏 | 日常创作,画布和工具并排 | ⭐⭐⭐⭐⭐ |
| 应用内分屏 画布+参考图 | 页面级分屏 | 需要参考图辅助创作的场景 | ⭐⭐⭐⭐ |
| EasyGo 1:1 版本对比 | 应用级分屏 | 作品修改前后的版本对比 | ⭐⭐⭐⭐ |
实际项目中,这三种方案可以组合使用。例如,默认使用 EasyGo 2:1 模式启动创作(画布+工具),当用户需要参考图时,在工具面板中点击"参考图"按钮,将工具面板切换为参考图显示模式。
八、与多设备形态适配的对比
8.1 两种能力的定位差异
| 维度 | 多设备形态适配(第 5.7 篇) | EasyGo / 应用内分屏 |
|---|---|---|
| 目标 | 让 UI 在不同屏幕上看起来正确 | 让用户在同一个屏幕上做更多事 |
| 手段 | 断点切换、响应式取值、栅格布局 | 分屏框架、页面联动、比例控制 |
| 触发条件 | 屏幕宽度变化自动触发 | 用户主动操作或应用逻辑触发 |
| 交互复杂度 | 隐式适配,用户无感知 | 显式分屏,用户有感知 |
| 状态管理 | @StorageLink 自动同步 | AppStorage / 事件总线通信 |
8.2 两种能力的协同使用
多设备形态适配解决了"布局在不同尺寸上是否好看"的问题,而 EasyGo 解决了"大屏上用户如何充分利用空间"的问题。两者是递进关系:
第 5.7 篇 → 第 7.13 篇
┌──────────────────────────────────────┐
│ 多设备形态适配(基础能力) │
│ ├── 断点系统:sm/md/lg/xl │
│ ├── 响应式布局:Tab 位置、栅格列数 │
│ └── 自适应布局:百分比、flexShrink │
│ │
│ + EasyGo / 应用内分屏(高级能力) │
│ ├── EasyGo:应用级分屏框架 │
│ ├── 应用内分屏:页面级分屏 │
│ └── 配置式接入:声明式 EasyGo 配置 │
└──────────────────────────────────────┘
具体到代码层面:
// 综合示例:根据断点决定是否使用 EasyGo 以及分屏比例
@Component
struct SmartCreativeExperience {
@StorageLink('currentBreakpoint') currentBreakpoint: string = 'sm';
private getEasyGoConfig(): EasyGoConfig | null {
const configMap = new BreakPointType<EasyGoConfig | null>({
sm: null, // 手机竖屏:不分屏,使用全屏画布
md: { // 小平板:画布+精简工具栏
leftPage: 'pages/CanvasEditor',
rightPage: 'pages/CompactToolPanel',
ratio: '2:1'
},
lg: { // 大平板:画布+完整工具栏
leftPage: 'pages/CanvasEditor',
rightPage: 'pages/CreativeToolPanel',
ratio: '2:1'
},
xl: { // 2in1:画布+完整工具栏+参考图区
leftPage: 'pages/CanvasEditor',
rightPage: 'pages/ExtendedToolPanel',
ratio: '3:2'
}
});
return configMap.getValue(this.currentBreakpoint);
}
}
九、最佳实践
9.1 渐进增强原则
不要在所有设备上不加区分地启用 EasyGo。推荐的实施策略是:
基础体验:手机竖屏(sm)
├── 全屏单栏布局
├── 通过 Tab 或弹出面板切换工具
└── 无分屏能力
增强体验:中大屏(md/lg)
├── EasyGo 2:1 创作模式
├── 画布占 2/3,工具面板占 1/3
└── 侧边栏始终可见
极致体验:超大屏(xl)
├── EasyGo 多模式切换
├── 创作模式 / 对比模式 / 预览模式
└── 可拖拽调节分屏比例
9.2 状态同步策略
EasyGo 左右两侧页面通过 AppStorage 实现状态同步:
// 左侧页面(画布)——更新工具状态
AppStorage.set('brushSize', newSize);
AppStorage.set('currentColor', newColor);
AppStorage.set('selectedTool', 'eraser');
// 右侧页面(工具面板)——监听工具状态
@StorageLink('brushSize') brushSize: number = 5;
@StorageLink('currentColor') currentColor: string = '#000000';
@StorageLink('selectedTool') selectedTool: string = 'brush';
9.3 生命周期管理
EasyGo 中的左右页面拥有独立的生命周期,需要注意:
- 两侧独立初始化:每个页面在
aboutToAppear中只加载自身需要的数据 - 不要重复请求:如果两侧都需要同一份数据(如用户信息),通过 AppStorage 共享而非各自请求
- 退出时清理:当 EasyGo 关闭时,两侧页面都会触发
aboutToDisappear
9.4 降级方案
当设备不支持 EasyGo 或用户不允许分屏时,需要有合理的降级方案:
async function startWithFallback(listPage: string, detailPage: string, params?: Object) {
try {
// 先检测设备是否支持 EasyGo
const isSupported = await parallelVision.isSupported();
if (isSupported) {
await parallelVision.startEasyGo({
leftPage: listPage,
rightPage: detailPage,
ratio: '1:2'
});
} else {
// 不支持则退化为普通跳转
throw new Error('EasyGo not supported');
}
} catch (e) {
// 降级:普通页面跳转
getUIContext().getRouter().pushUrl({
url: detailPage,
params: params
});
}
}
9.5 性能考量
| 注意事项 | 说明 |
|---|---|
| 避免两栏同时加载大量数据 | EasyGo 两侧页面会同时加载,注意控制初始数据量 |
| 懒加载 | 非可见区域使用 LazyForEach 延迟加载 |
| 状态去重 | 通过 AppStorage 共享状态,避免两侧独立请求同一数据 |
| 分屏切换动画 | 使用系统提供的过渡动画,避免自定义复杂动画导致掉帧 |
| 内存监控 | 分屏模式下同时渲染两个页面,注意监控内存使用 |
总结
平行视界 EasyGo 与应用内分屏是 HarmonyOS 7 在大屏多窗口交互领域的重要创新。它们不是简单的"把屏幕切成两半",而是一套完整的、由开发者主导的、配置驱动的分屏能力体系。
| 知识点 | 核心内容 | 关键要点 |
|---|---|---|
| EasyGo | 应用级分屏启动框架 | 1:2 / 2:1 / 购物模式 / 导航模式 |
| 应用内分屏 | 页面级 SplitScreen 组件 |
水平/垂直分割、比例可调 |
| 配置式接入 | JSON / 代码声明式配置 | 多模式预置、条件启用 |
| 与系统分屏区别 | 开发者控制力 | 比例、内容、联动均可控 |
| 与响应式布局整合 | 断点感知的分屏策略 | sm→单栏 / md+→分屏 |
| 项目应用 | 创作模式画布+工具面板 | 2:1 比例,AppStorage 状态同步 |
| 最佳实践 | 渐进增强 + 降级方案 | 检测支持能力,提供 fallback |
对于"画伴梦工厂"这样的创作工具,EasyGo 的应用内分屏能力几乎是为其量身定做的——用户在画布上创作时,所有工具触手可及;查看参考图时,无需离开创作界面;对比多个版本时,左右并排一目了然。这些体验的升级,正是从"好用的应用"到"出色的创作平台"的关键跨越。
思考题:在"画伴梦工厂"中,如果用户在 EasyGo 分屏模式下创作(左侧画布、右侧工具),此时用户旋转设备从横屏变为竖屏,断点从
lg变为sm。思考如何实现"从分屏到单栏"的平滑过渡?应该在BreakpointSystem的回调中关闭 EasyGo 并切换为全屏画布,还是让用户在单栏模式下通过底部面板切换工具?结合第 5.7 篇的断点系统和本文的 EasyGo API,给出你的设计方案。
更多推荐


所有评论(0)