项目已开源,开源地址: https://gitcode.com/nutpi/HarmonyosNextCaseStudyTutorial , 欢迎fork & star
效果演示
1. 引言
搜索栏是现代应用中常见的UI组件,通常包含一个搜索图标和一个输入框。在设计搜索栏时,我们常常需要精确控制组件之间的位置关系,使其既美观又符合用户的使用习惯。HarmonyOS NEXT的RelativeContainer组件提供了链中偏移(bias)功能,能够精确控制链中组件的位置,非常适合实现搜索栏这类需要精确定位的UI元素。本教程将详细讲解如何利用RelativeContainer的链中偏移功能实现一个美观、实用的搜索栏。
2. 链中偏移(Bias)概述
链中偏移是RelativeContainer链式布局的一个高级特性,它允许开发者通过设置偏移值(bias)来调整链在容器中的位置或链中组件的分布。偏移值的范围是0到1,其中0表示完全向链的起始端偏移,1表示完全向链的结束端偏移,0.5表示居中。
2.1 链中偏移的特性
- 精确控制:通过数值精确控制链的位置
- 范围限制:偏移值在0到1之间
- 方向性:水平链和垂直链都支持偏移
- 组件分布:可以影响链中组件的分布方式
3. 案例分析:搜索栏
3.1 完整代码
@Component export struct SearchBar { build() { RelativeContainer() { // 搜索图标 Image($r('app.media.search')) .width(20) .height(20) .id("searchIcon") .alignRules({ left: { anchor: "parent", align: HorizontalAlign.Start }, centerY: { anchor: "parent" } }) // 搜索输入框 TextInput({ placeholder: '搜索...' }) .width('80%') .height(36) .backgroundColor('#f5f5f5') .borderRadius(18) .padding({ left: 30 }) .id("searchInput") .alignRules({ left: { anchor: "searchIcon", align: HorizontalAlign.End }, centerY: { anchor: "parent" } }) } .chainMode([ { id: "searchChain", direction: Direction.HORIZONTAL, style: ChainStyle.PACKED, bias: 0.1, // 向左偏移 components: ["searchIcon", "searchInput"] } ]) .width('100%') .height(56) .backgroundColor('#ffffff') .padding({ left: 16, right: 16 }) } }
3.2 代码详解
3.2.1 RelativeContainer容器设置
RelativeContainer() { // 子组件 } .chainMode([ { id: "searchChain", direction: Direction.HORIZONTAL, style: ChainStyle.PACKED, bias: 0.1, // 向左偏移 components: ["searchIcon", "searchInput"] } ]) .width('100%') .height(56) .backgroundColor('#ffffff') .padding({ left: 16, right: 16 })
这部分代码创建了一个RelativeContainer容器,并设置了以下属性:
属性 |
值 |
说明 |
chainMode |
[...] |
定义链式布局数组 |
width |
'100%' |
容器宽度为父容器的100% |
height |
56 |
容器高度为56vp |
backgroundColor |
'#ffffff' |
背景色为白色 |
padding |
{ left: 16, right: 16 } |
左右内边距为16vp |
这里的关键是chainMode
属性,它定义了一个水平链:
- id: "searchChain" - 链的唯一标识符
- direction: Direction.HORIZONTAL - 链的方向为水平
- style: ChainStyle.PACKED - 链的样式为紧凑排列
- bias: 0.1 - 链的偏移值,向左偏移
- components: ["searchIcon", "searchInput"] - 链中包含的组件ID数组
这个水平链将搜索图标和搜索输入框连接起来,并通过bias值使它们整体向左偏移,创建一个视觉上更加平衡的布局。
3.2.2 搜索图标设置
Image($r('app.media.search')) .width(20) .height(20) .id("searchIcon") .alignRules({ left: { anchor: "parent", align: HorizontalAlign.Start }, centerY: { anchor: "parent" } })
搜索图标的关键属性设置:
属性 |
值 |
说明 |
width |
20 |
宽度为20vp |
height |
20 |
高度为20vp |
id |
"searchIcon" |
组件的唯一标识符,用于链式布局引用 |
alignRules.left |
{ anchor: "parent", align: HorizontalAlign.Start } |
左侧对齐父容器的左侧 |
alignRules.centerY |
{ anchor: "parent" } |
垂直居中于父容器 |
这里的关键点是为搜索图标设置了一个唯一的ID "searchIcon",这样链式布局就可以引用它。同时,图标被定位在容器的左侧并垂直居中。
3.2.3 搜索输入框设置
TextInput({ placeholder: '搜索...' }) .width('80%') .height(36) .backgroundColor('#f5f5f5') .borderRadius(18) .padding({ left: 30 }) .id("searchInput") .alignRules({ left: { anchor: "searchIcon", align: HorizontalAlign.End }, centerY: { anchor: "parent" } })
搜索输入框的关键属性设置:
属性 |
值 |
说明 |
width |
'80%' |
宽度为容器宽度的80% |
height |
36 |
高度为36vp |
backgroundColor |
'#f5f5f5' |
背景色为浅灰色 |
borderRadius |
18 |
边框圆角为18vp,使输入框呈现为圆角矩形 |
padding |
{ left: 30 } |
左内边距为30vp,为搜索图标留出空间 |
id |
"searchInput" |
组件的唯一标识符,用于链式布局引用 |
alignRules.left |
{ anchor: "searchIcon", align: HorizontalAlign.End } |
左侧对齐搜索图标的右侧 |
alignRules.centerY |
{ anchor: "parent" } |
垂直居中于父容器 |
搜索输入框的左侧对齐到了搜索图标的右侧,并垂直居中于容器。通过设置左内边距,为搜索图标留出了足够的空间,使得搜索图标看起来像是在输入框内部。
4. 链中偏移的高级应用
4.1 不同链式样式下的偏移效果
链中偏移在不同的链式样式下有不同的效果:
链式样式 |
偏移效果 |
ChainStyle.SPREAD |
影响链整体在容器中的位置 |
ChainStyle.SPREAD_INSIDE |
影响链整体在容器中的位置 |
ChainStyle.PACKED |
影响链整体在容器中的位置 |
4.2 组件级别的偏移
除了链级别的偏移,还可以为链中的单个组件设置偏移:
.alignRules({ left: { anchor: "parent", align: HorizontalAlign.Start, bias: 0.3 } })
4.3 垂直链中的偏移
垂直链也支持偏移:
.chainMode([ { id: "verticalChain", direction: Direction.VERTICAL, style: ChainStyle.PACKED, bias: 0.2, // 向上偏移 components: ["header", "content", "footer"] } ])
4.4 动态偏移
可以通过状态变量动态调整偏移值,实现动画效果:
@State searchBias: number = 0.1; // 在构建函数中 .chainMode([ { id: "searchChain", direction: Direction.HORIZONTAL, style: ChainStyle.PACKED, bias: this.searchBias, components: ["searchIcon", "searchInput"] } ]) // 在事件处理函数中 onFocus() { this.searchBias = 0.0; // 聚焦时完全左对齐 } onBlur() { this.searchBias = 0.1; // 失焦时恢复原来的偏移 }
5. 搜索栏的最佳实践
5.1 搜索栏的布局变体
搜索栏有多种常见的布局变体:
布局变体 |
实现方法 |
图标在输入框内左侧 |
输入框设置左内边距,图标通过绝对定位放置在输入框内 |
图标在输入框外左侧 |
使用链式布局连接图标和输入框,设置适当的间距 |
图标在输入框内右侧 |
输入框设置右内边距,图标通过绝对定位放置在输入框内 |
带取消按钮的搜索栏 |
链中添加取消按钮组件,通过状态变量控制其显示与隐藏 |
5.2 搜索栏的交互设计
搜索栏通常需要响应用户的交互:
@State isFocused: boolean = false; // 在构建函数中 TextInput({ placeholder: '搜索...' }) .width(this.isFocused ? '70%' : '80%') // 聚焦时宽度变小,为取消按钮留出空间 .onFocus(() => { this.isFocused = true; }) .onBlur(() => { this.isFocused = false; }) if (this.isFocused) { Text('取消') .fontSize(14) .onClick(() => { // 取消搜索 }) }
6. 实际应用场景
链中偏移布局在以下场景中特别有用:
- 搜索栏:精确控制搜索图标和输入框的位置
- 表单布局:调整表单元素的分布
- 卡片布局:控制卡片内元素的分布
- 导航栏:调整导航项的分布
7. 总结
链中偏移是RelativeContainer链式布局的一个强大特性,特别适合需要精确控制组件位置的场景。