项目已开源,开源地址: https://gitcode.com/nutpi/HarmonyosNextCaseStudyTutorial , 欢迎fork & star
效果演示
1. 引言
在现代UI设计中,按照特定比例分配空间的布局需求非常常见,例如黄金分割比例的内容区域、按照特定比例分配的多列布局等。HarmonyOS NEXT的RelativeContainer组件提供了链中节点权重(chainWeight)功能,能够按照指定的权重比例分配链中组件的空间,实现灵活的比例布局。本教程将详细讲解如何利用RelativeContainer的链中节点权重功能实现灵活的比例布局,帮助你掌握这一强大的布局技术。
2. 链中节点权重(ChainWeight)概述
链中节点权重是RelativeContainer链式布局的一个高级特性,它允许开发者为链中的每个组件分配权重值,系统会根据这些权重值按比例分配可用空间。权重值可以是任意正数,组件获得的空间比例等于其权重值除以所有组件权重值的总和。
2.1 链中节点权重的特性
- 比例分配:根据权重比例分配空间
- 灵活调整:通过调整权重值实现不同的分配比例
- 链式样式兼容:可以与不同的链式样式(ChainStyle)结合使用
- 动态调整:可以通过状态变量动态调整权重值
3. 案例分析:权重布局
3.1 完整代码
@Component export struct WeightedLayout { build() { RelativeContainer() { // 左侧区域 Column() { Text('左侧区域') .fontSize(16) .fontColor('#ffffff') } .width('100%') .height('100%') .backgroundColor('#007DFF') .justifyContent(FlexAlign.Center) .id("leftArea") .alignRules({ left: { anchor: "parent", align: HorizontalAlign.Start }, top: { anchor: "parent", align: VerticalAlign.Top }, bottom: { anchor: "parent", align: VerticalAlign.Bottom } }) // 中间区域 Column() { Text('中间区域') .fontSize(16) .fontColor('#ffffff') } .width('100%') .height('100%') .backgroundColor('#FF7D00') .justifyContent(FlexAlign.Center) .id("middleArea") .alignRules({ left: { anchor: "leftArea", align: HorizontalAlign.End }, top: { anchor: "parent", align: VerticalAlign.Top }, bottom: { anchor: "parent", align: VerticalAlign.Bottom } }) // 右侧区域 Column() { Text('右侧区域') .fontSize(16) .fontColor('#ffffff') } .width('100%') .height('100%') .backgroundColor('#7D00FF') .justifyContent(FlexAlign.Center) .id("rightArea") .alignRules({ left: { anchor: "middleArea", align: HorizontalAlign.End }, right: { anchor: "parent", align: HorizontalAlign.End }, top: { anchor: "parent", align: VerticalAlign.Top }, bottom: { anchor: "parent", align: VerticalAlign.Bottom } }) } .chainMode([ { id: "horizontalChain", direction: Direction.HORIZONTAL, style: ChainStyle.SPREAD, components: ["leftArea", "middleArea", "rightArea"], chainWeights: [1, 2, 1] // 1:2:1的比例 } ]) .width('100%') .height(200) } }
3.2 代码详解
3.2.1 RelativeContainer容器设置
RelativeContainer() { // 子组件 } .chainMode([ { id: "horizontalChain", direction: Direction.HORIZONTAL, style: ChainStyle.SPREAD, components: ["leftArea", "middleArea", "rightArea"], chainWeights: [1, 2, 1] // 1:2:1的比例 } ]) .width('100%') .height(200)
这部分代码创建了一个RelativeContainer容器,并设置了以下属性:
属性 |
值 |
说明 |
chainMode |
[...] |
定义链式布局数组 |
width |
'100%' |
容器宽度为父容器的100% |
height |
200 |
容器高度为200vp |
这里的关键是chainMode
属性,它定义了一个水平链:
- id: "horizontalChain" - 链的唯一标识符
- direction: Direction.HORIZONTAL - 链的方向为水平
- style: ChainStyle.SPREAD - 链的样式为均匀分布
- components: ["leftArea", "middleArea", "rightArea"] - 链中包含的组件ID数组
- chainWeights: [1, 2, 1] - 链中组件的权重数组,按照1:2:1的比例分配空间
这个水平链将三个区域组件连接起来,并根据指定的权重比例分配空间,使中间区域的宽度是左右区域的两倍。
3.2.2 左侧区域设置
Column() { Text('左侧区域') .fontSize(16) .fontColor('#ffffff') } .width('100%') .height('100%') .backgroundColor('#007DFF') .justifyContent(FlexAlign.Center) .id("leftArea") .alignRules({ left: { anchor: "parent", align: HorizontalAlign.Start }, top: { anchor: "parent", align: VerticalAlign.Top }, bottom: { anchor: "parent", align: VerticalAlign.Bottom } })
左侧区域的关键属性设置:
属性 |
值 |
说明 |
width |
'100%' |
宽度为父容器的100%(实际宽度将由链中权重决定) |
height |
'100%' |
高度为父容器的100% |
backgroundColor |
'#007DFF' |
背景色为蓝色 |
justifyContent |
FlexAlign.Center |
内容居中对齐 |
id |
"leftArea" |
组件的唯一标识符,用于链式布局引用 |
alignRules |
{...} |
对齐规则 |
这里的关键点是为左侧区域设置了一个唯一的ID "leftArea",这样链式布局就可以引用它。同时,通过alignRules将其左侧对齐到父容器的左侧,顶部和底部分别对齐到父容器的顶部和底部,使其占据容器的整个高度。
3.2.3 中间区域设置
Column() { Text('中间区域') .fontSize(16) .fontColor('#ffffff') } .width('100%') .height('100%') .backgroundColor('#FF7D00') .justifyContent(FlexAlign.Center) .id("middleArea") .alignRules({ left: { anchor: "leftArea", align: HorizontalAlign.End }, top: { anchor: "parent", align: VerticalAlign.Top }, bottom: { anchor: "parent", align: VerticalAlign.Bottom } })
中间区域的关键属性设置:
属性 |
值 |
说明 |
width |
'100%' |
宽度为父容器的100%(实际宽度将由链中权重决定) |
height |
'100%' |
高度为父容器的100% |
backgroundColor |
'#FF7D00' |
背景色为橙色 |
justifyContent |
FlexAlign.Center |
内容居中对齐 |
id |
"middleArea" |
组件的唯一标识符,用于链式布局引用 |
alignRules |
{...} |
对齐规则 |
中间区域的左侧对齐到左侧区域的右侧,顶部和底部分别对齐到父容器的顶部和底部。
3.2.4 右侧区域设置
Column() { Text('右侧区域') .fontSize(16) .fontColor('#ffffff') } .width('100%') .height('100%') .backgroundColor('#7D00FF') .justifyContent(FlexAlign.Center) .id("rightArea") .alignRules({ left: { anchor: "middleArea", align: HorizontalAlign.End }, right: { anchor: "parent", align: HorizontalAlign.End }, top: { anchor: "parent", align: VerticalAlign.Top }, bottom: { anchor: "parent", align: VerticalAlign.Bottom } })
右侧区域的关键属性设置:
属性 |
值 |
说明 |
width |
'100%' |
宽度为父容器的100%(实际宽度将由链中权重决定) |
height |
'100%' |
高度为父容器的100% |
backgroundColor |
'#7D00FF' |
背景色为紫色 |
justifyContent |
FlexAlign.Center |
内容居中对齐 |
id |
"rightArea" |
组件的唯一标识符,用于链式布局引用 |
alignRules |
{...} |
对齐规则 |
右侧区域的左侧对齐到中间区域的右侧,右侧对齐到父容器的右侧,顶部和底部分别对齐到父容器的顶部和底部。
4. 链中节点权重的高级应用
4.1 不同链式样式下的权重效果
链中节点权重在不同的链式样式下有不同的效果:
链式样式 |
权重效果 |
ChainStyle.SPREAD |
按权重比例分配所有可用空间 |
ChainStyle.SPREAD_INSIDE |
按权重比例分配除首尾组件外的可用空间 |
ChainStyle.PACKED |
按权重比例分配组件之间的间距 |
4.2 黄金分割比例布局
可以使用黄金分割比例(约1:1.618)创建视觉上和谐的布局:
.chainMode([ { id: "goldenRatioChain", direction: Direction.HORIZONTAL, style: ChainStyle.SPREAD, components: ["leftArea", "rightArea"], chainWeights: [1, 1.618] // 黄金分割比例 } ])
4.3 垂直链中的权重分配
垂直链也支持权重分配:
.chainMode([ { id: "verticalChain", direction: Direction.VERTICAL, style: ChainStyle.SPREAD, components: ["header", "content", "footer"], chainWeights: [1, 4, 1] // 1:4:1的比例 } ])
4.4 动态权重
可以通过状态变量动态调整权重值,实现布局的动态变化:
@State leftWeight: number = 1; @State middleWeight: number = 2; @State rightWeight: number = 1; // 在构建函数中 .chainMode([ { id: "horizontalChain", direction: Direction.HORIZONTAL, style: ChainStyle.SPREAD, components: ["leftArea", "middleArea", "rightArea"], chainWeights: [this.leftWeight, this.middleWeight, this.rightWeight] } ]) // 在事件处理函数中 onExpandLeft() { this.leftWeight = 2; this.middleWeight = 1; this.rightWeight = 1; }
5. 比例布局的最佳实践
5.1 常见的比例布局
以下是一些常见的比例布局及其实现方法:
布局类型 |
实现方法 |
等分布局 |
所有组件权重相等,如[1, 1, 1] |
主次布局 |
主要区域权重大,次要区域权重小,如[2, 1] |
黄金分割 |
按照黄金比例设置权重,如[1, 1.618] |
自定义比例 |
根据设计需求设置特定比例,如[3, 5, 2] |
5.2 响应式比例布局
可以根据屏幕尺寸动态调整比例:
@State screenWidth: number = 0; // 在aboutToAppear生命周期函数中获取屏幕宽度 aboutToAppear() { this.screenWidth = px2vp(window.getWindowWidth()); } // 根据屏幕宽度计算权重 getWeights() { if (this.screenWidth < 600) { return [1, 1]; // 窄屏幕使用1:1比例 } else { return [1, 2]; // 宽屏幕使用1:2比例 } }
6. 实际应用场景
链中节点权重分配在以下场景中特别有用:
- 多列布局:按照特定比例分配多列的宽度
- 分割视图:创建可调整比例的分割视图
- 内容布局:按照视觉重要性分配内容区域
- 响应式设计:根据屏幕尺寸动态调整布局比例
7. 总结
链中节点权重分配是RelativeContainer链式布局的一个强大特性,特别适合创建按照特定比例分配空间的布局。