HarmonyOS 多设备短视频开发 : 18 — 侧边栏 SideBarContainer 与分栏交互
18 — 侧边栏 SideBarContainer 与分栏交互
一、引言

PC 与平板宽屏下,"左侧导航 + 右侧内容"是信息密度最高、操作效率最好的信息架构。HarmonyOS 的 SideBarContainer 提供 sidebar/content 双区域布局。本项目 PC 端(products/pc/src/main/ets/view/Index.ets)用它承载主导航与内容区,并在内容区内嵌套 Navigation 实现评论/个人作品的二级分栏,形成"侧边栏 → 页签 → 内容区 → 侧面板"的分层导航体系。本文拆解其实现细节。
二、SideBarContainer 结构与属性
SideBarContainer 的第一个子组件是侧边栏,第二个是内容区:
SideBarContainer(SideBarContainerType.Embed) {
Column() {
/* 侧边栏:Logo + 菜单列表 */
}
Column() {
this.ContentBuilder({ index: this.selectedIndex })
}
}
.sideBarWidth(112)
.autoHide(false)
.divider({ strokeWidth: 0.5, color: '#ff646466' })
.showControlButton(false)| 属性 | 说明 | 本项目取值 |
| sideBarWidth | 侧边栏宽度 | 112vp 固定 |
| autoHide | 是否自动隐藏 | false(常驻) |
| showControlButton | 是否显示系统折叠按钮 | false(自绘菜单) |
| divider | 侧栏与内容区分隔线 | 0.5vp 半透明 |
SideBarContainerType.Embed 表示侧边栏嵌入内容区而非悬浮覆盖,内容区宽度实时重排。
三、PC 端侧边栏菜单实现
菜单由 MSVDataModel 数组驱动,Repeat 渲染,选中项高亮:
List() {
Repeat<MSVDataModel>(this.data)
.each((item: RepeatItem<MSVDataModel>) => {
ListItem() {
Row({ space: 8 }) {
MSVTextIcon({ src: this.selectedIndex === item.index ? item.item.icon : item.item.iconDark, iconSize: 24 })
Text(item.item.text)
.fontColor(this.selectedIndex === item.index ? '#ffffff' : '#c7c7c8')
}
.height(40).borderRadius(8)
.backgroundColor(this.selectedIndex === item.index ? $r('app.color.all_icon_bg_10') : Color.Transparent)
}
.onClick(() => { this.selectedIndex = item.index; }) // 切换内容区
})
.virtualScroll({ totalCount: this.data.length })
}virtualScroll 启用虚拟滚动,长菜单下保证帧率稳定;selectedIndex 是内容区刷新的唯一驱动源。
四、内容区与页签联动
内容区根据 selectedIndex 切换页面,首页内再嵌套 Navigation(ContentBuilder):
@Builder
ContentBuilder(params: ContentParamsModel) {
if (params.index === 0) {
Navigation(this.pathStack) {
Stack({ alignContent: Alignment.TopEnd }) { recommend() }
}
.navBarWidthRange(['66%', '100%'])
.navBarWidth('66%')
.hideBackButton(true)
.hideTitleBar(true)
.mode(this.showSideComment || this.showSideIndividual ? NavigationMode.Split : NavigationMode.Stack)
} else if (params.index === 1) {
follow()
} else if (params.index === 5) {
mine()
}
}内容区导航宽度取 '66%',为右侧侧面板预留空间,与 default 产品按断点取固定宽度的策略互补。
五、分栏模式下评论与个人作品的侧面板
打开评论时置 showSideComment = true 并 pushPathByName('SplitComment'),Navigation 自动切 Split 模式,NavDestination 作为右侧面板展开,主内容区不退出:
.onAction(() => {
if (this.showSideComment || this.windowInfo.widthBp === WidthBreakpoint.WIDTH_XS) return;
if (this.windowInfo.widthBp > WidthBreakpoint.WIDTH_SM) {
this.showSideComment = true;
this.pathStack.pushPathByName('SplitComment', null); // 大屏:侧面板
} else {
this.showComment = true; // 小屏:半模态
}
})SplitComment(products/default/.../view/SplitComment.ets)自定义标题栏,点击关闭时出栈并复位开关:
@Builder
CustomTitleBuilder() {
Column() {
Column().width(CommonConstants.FULL_PERCENT).height(36)
.linearGradient({ direction: GradientDirection.Bottom, colors: [['#4D000000', 0.0], ['#00000000', 1.0]] })
Row() {
Text($r('app.string.comment_title', this.commentCount))
Row() { SymbolGlyph($r('sys.symbol.xmark')).fontSize(18) }
.width(40).aspectRatio(1).borderRadius(CommonConstants.HALF_PERCENT)
.onClick(() => { this.pathStack.pop(); this.showSideComment = false; })
}
}
}个人作品侧面板同理:showSideIndividual = true 后 pushPathByName('IndividualByRouter', null)。
六、主内容区联动刷新与点击关闭
侧面板打开时主内容区 hitTest 切换为 Block 拦截点击,配合 TapGesture 与 onGestureRecognizerJudgeBegin 实现"点空白收起侧栏":
.hitTestBehavior(this.showSideComment || this.showSideIndividual ? HitTestMode.Block : HitTestMode.Default)
.gesture(TapGesture())
.onGestureRecognizerJudgeBegin((event, current) => {
if (current && (current.getType() === GestureControl.GestureType.TAP_GESTURE ||
current.getType() === GestureControl.GestureType.CLICK)) {
if (this.showSideComment || this.showSideIndividual) {
this.pathStack.pop();
this.showSideComment = false;
this.showSideIndividual = false;
return GestureJudgeResult.REJECT;
}
}
return GestureJudgeResult.CONTINUE;
})被拦截的点击不会继续透传给视频播放层,避免误触播放/暂停。
七、总结与最佳实践
- 侧边栏常驻用 autoHide(false) + showControlButton(false),菜单自绘保证全设备视觉一致。
- 侧面板优先用 Navigation Split 模式而非弹窗,大屏下避免模态割裂、内容上下文不丢失。
- 断点 + 布尔开关(showSideComment/showSideIndividual)驱动形态:大屏分栏、手机半模态,一套业务逻辑。
- divider 与选中高亮提升信息层级;virtualScroll 优化长菜单滚动性能。
- selectedIndex 单一驱动源 + 声明式刷新,保证侧边栏与内容区联动可靠、无状态漂移。
更多推荐




所有评论(0)