项目已开源,开源地址: https://gitcode.com/nutpi/HarmonyosNextCaseStudyTutorial , 欢迎fork & star
效果演示
1. 引言
底部导航栏是移动应用中最常见的导航元素之一,它通常包含多个均匀分布的图标或按钮,用于在应用的主要功能之间切换。在HarmonyOS NEXT中,RelativeContainer组件提供了强大的链式布局(Chain)功能,能够轻松实现元素的均匀分布,非常适合底部导航栏的实现。本教程将详细讲解如何利用RelativeContainer的水平链布局功能实现一个美观、均匀分布的底部导航栏。
2. 链式布局(Chain)概述
链式布局是RelativeContainer提供的一种特殊的布局方式,它可以将一组组件按照特定的方式排列在一条直线上,并控制它们之间的间距和分布方式。链式布局可以是水平的或垂直的,并支持多种分布模式。
2.1 链式布局的特性
- 方向性:可以是水平的或垂直的
- 分布模式:支持多种分布方式,如均匀分布、两端对齐等
- 组件连接:将多个组件连接成一条链
- 自动间距:根据分布模式自动计算组件之间的间距
3. 案例分析:底部导航栏
3.1 完整代码
@Component export struct BottomNav { build() { RelativeContainer() { // 首页图标 Image($r('app.media.home')) .width(24) .height(24) .id("home") .alignRules({ left: { anchor: "parent", align: HorizontalAlign.Start }, bottom: { anchor: "parent", align: VerticalAlign.Bottom } }) // 消息图标 Image($r('app.media.message')) .width(24) .height(24) .id("message") .alignRules({ left: { anchor: "parent", align: HorizontalAlign.Center }, bottom: { anchor: "parent", align: VerticalAlign.Bottom } }) // 我的图标 Image($r('app.media.profile')) .width(24) .height(24) .id("profile") .alignRules({ left: { anchor: "parent", align: HorizontalAlign.End }, bottom: { anchor: "parent", align: VerticalAlign.Bottom } }) } .chainMode([ { id: "horizontalChain", direction: Direction.HORIZONTAL, style: ChainStyle.SPREAD, components: ["home", "message", "profile"] } ]) .width('100%') .height(56) .backgroundColor('#ffffff') } }
3.2 代码详解
3.2.1 RelativeContainer容器设置
RelativeContainer() { // 子组件 } .chainMode([ { id: "horizontalChain", direction: Direction.HORIZONTAL, style: ChainStyle.SPREAD, components: ["home", "message", "profile"] } ]) .width('100%') .height(56) .backgroundColor('#ffffff')
这部分代码创建了一个RelativeContainer容器,并设置了以下属性:
属性 |
值 |
说明 |
chainMode |
[...] |
定义链式布局数组 |
width |
'100%' |
容器宽度为父容器的100% |
height |
56 |
容器高度为56vp |
backgroundColor |
'#ffffff' |
背景色为白色 |
这里的关键是chainMode
属性,它定义了一个水平链:
- id: "horizontalChain" - 链的唯一标识符
- direction: Direction.HORIZONTAL - 链的方向为水平
- style: ChainStyle.SPREAD - 链的样式为均匀分布
- components: ["home", "message", "profile"] - 链中包含的组件ID数组
这个水平链将三个图标组件连接起来,并使它们在容器中均匀分布。
3.2.2 首页图标设置
Image($r('app.media.home')) .width(24) .height(24) .id("home") .alignRules({ left: { anchor: "parent", align: HorizontalAlign.Start }, bottom: { anchor: "parent", align: VerticalAlign.Bottom } })
首页图标的关键属性设置:
属性 |
值 |
说明 |
width |
24 |
宽度为24vp |
height |
24 |
高度为24vp |
id |
"home" |
组件的唯一标识符,用于链式布局引用 |
alignRules.left |
{ anchor: "parent", align: HorizontalAlign.Start } |
左侧对齐父容器的左侧 |
alignRules.bottom |
{ anchor: "parent", align: VerticalAlign.Bottom } |
底部对齐父容器的底部 |
这里的关键点是为首页图标设置了一个唯一的ID "home",这样链式布局就可以引用它。同时,图标被定位在容器的左下角。
3.2.3 消息图标设置
Image($r('app.media.message')) .width(24) .height(24) .id("message") .alignRules({ left: { anchor: "parent", align: HorizontalAlign.Center }, bottom: { anchor: "parent", align: VerticalAlign.Bottom } })
消息图标的关键属性设置:
属性 |
值 |
说明 |
width |
24 |
宽度为24vp |
height |
24 |
高度为24vp |
id |
"message" |
组件的唯一标识符,用于链式布局引用 |
alignRules.left |
{ anchor: "parent", align: HorizontalAlign.Center } |
左侧对齐父容器的中心 |
alignRules.bottom |
{ anchor: "parent", align: VerticalAlign.Bottom } |
底部对齐父容器的底部 |
消息图标被定位在容器的底部中心位置。
3.2.4 我的图标设置
Image($r('app.media.profile')) .width(24) .height(24) .id("profile") .alignRules({ left: { anchor: "parent", align: HorizontalAlign.End }, bottom: { anchor: "parent", align: VerticalAlign.Bottom } })
我的图标的关键属性设置:
属性 |
值 |
说明 |
width |
24 |
宽度为24vp |
height |
24 |
高度为24vp |
id |
"profile" |
组件的唯一标识符,用于链式布局引用 |
alignRules.left |
{ anchor: "parent", align: HorizontalAlign.End } |
左侧对齐父容器的右侧 |
alignRules.bottom |
{ anchor: "parent", align: VerticalAlign.Bottom } |
底部对齐父容器的底部 |
我的图标被定位在容器的右下角。
4. 链式布局的高级应用
4.1 链式布局样式
RelativeContainer提供了多种链式布局样式:
链式样式 |
说明 |
效果 |
ChainStyle.SPREAD |
均匀分布,组件之间的间距相等 |
组件均匀分布在容器中 |
ChainStyle.SPREAD_INSIDE |
两端对齐,首尾组件贴近容器边缘,中间组件均匀分布 |
首尾组件贴边,中间均匀分布 |
ChainStyle.PACKED |
紧凑排列,组件紧密排列在一起 |
组件紧密排列在容器中心 |
4.2 链式布局偏移
可以通过设置链的偏移(bias)来调整链在容器中的位置:
.chainMode([ { id: "horizontalChain", direction: Direction.HORIZONTAL, style: ChainStyle.SPREAD, components: ["home", "message", "profile"], bias: 0.3 // 链向左偏移 } ])
4.3 垂直链式布局
除了水平链,还可以创建垂直链:
.chainMode([ { id: "verticalChain", direction: Direction.VERTICAL, style: ChainStyle.SPREAD, components: ["button1", "button2", "button3"] } ])
4.4 多链组合
可以在同一个容器中定义多个链,实现复杂的布局:
.chainMode([ { id: "horizontalChain1", direction: Direction.HORIZONTAL, style: ChainStyle.SPREAD, components: ["home", "message", "profile"] }, { id: "verticalChain1", direction: Direction.VERTICAL, style: ChainStyle.SPREAD, components: ["header", "content", "footer"] } ])
5. 底部导航栏的最佳实践
5.1 导航项的布局
底部导航栏通常包含图标和文本标签,可以使用以下方式布局:
布局方式 |
实现方法 |
图标在上,文本在下 |
使用垂直链连接每个导航项的图标和文本 |
只显示图标 |
只使用图标组件,通过水平链均匀分布 |
图标和文本并排 |
使用水平链连接图标和文本,再使用另一个水平链连接多个导航项 |
5.2 导航项的选中状态
可以通过状态变量控制导航项的选中状态:
@State currentTab: number = 0; // 在构建函数中 Image(this.currentTab === 0 ? $r('app.media.home_selected') : $r('app.media.home')) .width(24) .height(24) .id("home") .onClick(() => { this.currentTab = 0; })
6. 实际应用场景
水平链布局在以下场景中特别有用:
- 底部导航栏:均匀分布的导航图标
- 工具栏:均匀分布的工具按钮
- 标签页:均匀分布的标签
- 评分组件:均匀分布的星星图标
7. 总结
链式布局是RelativeContainer提供的强大功能,特别适合创建均匀分布的组件布局。