文章目录
项目已开源,开源地址: 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提供的强大功能,特别适合创建均匀分布的组件布局。