在 HarmonyOS ArkTS 页面开发中,布局是 UI 搭建的基础。日常项目高频使用选项卡 Tabs、轮播 Swiper、相对布局 RelativeContainer三大核心组件,本文结合课堂宿舍实战案例,从原理、API、实战代码、使用场景梳理。
一、整体组件分类梳理
| 组件 | 核心作用 | 适用场景 |
|---|---|---|
| Tabs 选项卡 | 多页面分类切换,生成底部 / 顶部导航栏 | APP 首页底部导航(首页 / 发现 / 我的)、分类标签页 |
| Swiper 轮播 | 横向滑动切换多页面,支持自动轮播、循环、指示器 | 广告轮播、宿舍床位轮播、图片横幅 |
| RelativeContainer 相对布局 | 组件之间互相锚定、相对定位,减少布局嵌套 | 不规则排版、多组件错落排布(宿舍床位卡片排版) |
二、组件详解和实战代码(结合宿舍项目案例)
1. Tabs 选项卡:多标签页面切换
1.1 原理说明
Tabs 由Tabs容器 + TabContent页面 + tabBar导航文字三部分组成:
- 一个
TabContent对应一个页面 + 底部一个导航按钮; .tabBar("文字")紧跟 TabContent 后,定义底部标签显示内容;.barPosition(BarPosition.Bottom/Top)控制导航栏在页面底部 / 顶部。
1.2 实战:宿舍三级标签(宿舍介绍 / 床位轮播 / 床位详情)
@Entry @Component struct LianXi4 { build() { // Tabs外层标签容器 Tabs() { // 标签1:宿舍介绍页 TabContent() { Text('欢迎来到新宿舍,下面是宿舍信息情况') .width('100%').height(100).fontSize(35) }.padding(10) .tabBar('宿舍') // 底部导航文字 // 标签2:床位轮播页(内嵌Swiper轮播) TabContent() { Swiper() { Text('一号铺').width('100%').height(100).backgroundColor(Color.Blue).fontSize(35) Text('二号铺').width('100%').height(100).backgroundColor(Color.Pink).fontSize(35) Text('三号铺').width('100%').height(100).backgroundColor(Color.Brown).fontSize(35) Text('四号铺').width('100%').height(100).backgroundColor(Color.Red).fontSize(35) Text('五号铺').width('100%').height(100).backgroundColor(Color.Orange).fontSize(35) } .width('100%').height(100) .indicator(true) // 开启轮播圆点指示器 .autoPlay(true) // 开启自动轮播 .interval(300) // 轮播间隔300ms .loop(true) // 首尾无限循环 }.padding(10) .tabBar('名字') // 标签3:床位详情页(内嵌RelativeContainer相对布局) TabContent() { RelativeContainer() { // 一号铺:锚定父容器左上角 Text('517一号铺').id('title').fontSize(28).padding(10).backgroundColor(Color.Green) .alignRules({ top:{anchor:'__container__',align:VerticalAlign.Top}, left:{anchor:'__container__',align:HorizontalAlign.Start} }) // 二号铺:锚定一号铺右侧 Text('517二号铺').id('title1').fontSize(28).padding(10).backgroundColor(Color.Gray) .alignRules({ top:{anchor:'title',align:VerticalAlign.Top}, left:{anchor:'title',align:HorizontalAlign.End} }) // 三号铺:锚定一号铺下方 Text('517三号铺').id('title2').fontSize(28).padding(10).backgroundColor(Color.Gray) .alignRules({ top:{anchor:'title',align:VerticalAlign.Bottom}, left:{anchor:'title',align:HorizontalAlign.Start} }) // 后续4~8号铺依次锚定前一个组件排版 Text('517四号铺').id('title3').fontSize(28).padding(10).backgroundColor(Color.Orange) .alignRules({top:{anchor:'title2',align:VerticalAlign.Top},left:{anchor:'title2',align:HorizontalAlign.End}}) Text('517五号铺').id('title4').fontSize(28).padding(10).backgroundColor(Color.Blue) .alignRules({top:{anchor:'title2',align:VerticalAlign.Bottom},left:{anchor:'title2',align:HorizontalAlign.Start}}) Text('517六号铺').id('title5').fontSize(28).padding(10).backgroundColor(Color.Brown) .alignRules({top:{anchor:'title4',align:VerticalAlign.Top},left:{anchor:'title4',align:HorizontalAlign.End}}) Text('517七号铺').id('title6').fontSize(28).padding(10).backgroundColor(Color.Gray) .alignRules({top:{anchor:'title4',align:VerticalAlign.Bottom},left:{anchor:'title4',align:HorizontalAlign.Start}}) Text('517八号铺').id('title7').fontSize(28).padding(10).backgroundColor(Color.Orange) .alignRules({top:{anchor:'title6',align:VerticalAlign.Top},left:{anchor:'title6',align:HorizontalAlign.End}}) }.height('100%') }.tabBar('床号') } .barPosition(BarPosition.Bottom) // 导航栏放底部 } }1.3 运行效果
页面底部出现【宿舍、名字、床号】三个标签,点击切换对应页面:
- 宿舍:宿舍简介文字;
- 名字:床位横向自动轮播;
- 床号:8 个床位错落相对排版。
2. Swiper 轮播组件:自动横向滑动
2.1 核心属性汇总
| 属性 | 作用 |
|---|---|
.indicator(true) | 开启底部小圆点页码指示器 |
.autoPlay(true) | 开启自动播放轮播 |
.interval(毫秒) | 自动切换间隔时间,3000=3 秒 |
.loop(true) | 开启无限循环,滑到末尾切回第一页 |
.width/height | 固定轮播容器尺寸 |
2.2 最简基础案例
@Entry @Component struct SwiperDemo { build() { Column(){ Swiper(){ Text('你好').width('100%').height(100).backgroundColor(Color.Blue).fontSize(35) Text('世界').width('100%').height(100).backgroundColor(Color.Pink).fontSize(35) Text('伟大').width('100%').height(100).backgroundColor(Color.Brown).fontSize(35) Text('中国').width('100%').height(100).backgroundColor(Color.Red).fontSize(35) Text('承德').width('100%').height(100).backgroundColor(Color.Orange).fontSize(35) } .width('100%').height(100) .indicator(true).autoPlay(true).interval(300).loop(true) }.padding(10) } }3. RelativeContainer 相对布局:锚点定位精髓
3.1 原理
相对布局不依赖固定坐标,靠锚点(anchor)+ 对齐方式(align)定位:
anchor:'__container__':锚定父容器(整个 RelativeContainer);anchor:'组件id':锚定其他子组件(实现 A 在 B 右边 / 下边);- 水平枚举:
HorizontalAlign.Start(靠左)、Center(居中)、End(靠右); - 垂直枚举:
VerticalAlign.Top(靠上)、Center(居中)、Bottom(靠下)。
3.2 经典案例 1:院校标题上下排版
@Entry @Component struct SchoolDemo { build() { RelativeContainer() { // 第一个标题id=title,贴容器左上角 Text('河北软件职业技术学院').id('title').fontSize(28).fontWeight(FontWeight.Bolder) .alignRules({ top:{anchor:'__container__',align:VerticalAlign.Top}, left:{anchor:'__container__',align:HorizontalAlign.Start} }).padding(10) // 第二个标题锚在title底部、左对齐 Text('计算机应用工程系').id('title2').fontSize(24) .alignRules({ top:{anchor:'title',align:VerticalAlign.Bottom}, left:{anchor:'title',align:HorizontalAlign.Start} }).padding(30) }.width('100%').height('100%') } }3.3 经典案例 2:多方块错落 + 居中按钮
@Entry @Component struct RelDemo { build() { RelativeContainer(){ Text('相对布局的案例').id('title').fontSize(22).fontWeight(FontWeight.Bold) .alignRules({top:{anchor:'__container__',align:VerticalAlign.Top},left:{anchor:'__container__',align:HorizontalAlign.Start}}) .backgroundColor(Color.Brown).width(150).height(150) // 第二个方块在title右侧 Text('相对布局的案例').id('title2').fontSize(22).fontWeight(FontWeight.Bold) .alignRules({top:{anchor:'title',align:VerticalAlign.Top},left:{anchor:'title',align:HorizontalAlign.End}}) .backgroundColor(Color.Pink).width(150).height(150) // 第三个方块在title下方 Text('相对布局的案例').id('title3').fontSize(22).fontWeight(FontWeight.Bold) .alignRules({top:{anchor:'title',align:VerticalAlign.Bottom},left:{anchor:'title',align:HorizontalAlign.Start}}) .backgroundColor(Color.Gray).width(150).height(150) // 第四个方块在title3右侧 Text('相对布局的案例').id('title4').fontSize(22).fontWeight(FontWeight.Bold) .alignRules({top:{anchor:'title3',align:VerticalAlign.Top},left:{anchor:'title3',align:HorizontalAlign.End}}) .backgroundColor(Color.Green).width(150).height(150) // 按钮在页面正中间 Button('基础按钮').id('basebn').width(100).height(40) .alignRules({top:{anchor:'__container__',align:VerticalAlign.Center},left:{anchor:'__container__',align:HorizontalAlign.Center}}) } } }三、开发避坑总结
- 组件命名不能用系统关键字:
index是系统内置属性,struct index{}会编译报错,新建ArkTS文件写入; - RelativeContainer 必须设置 id:需要被其他组件锚定的控件必须
.id('自定义名称'),否则无法引用,切记不可重复; - Tabs 嵌套组件层级:Swiper/RelativeContainer 写在 TabContent 内部,不能直接写在 Tabs 根节点;
四、拓展知识点:DynamicLayout 动态布局
API24 + 新增DynamicLayout动态布局容器,支持运行时一键切换 Row 横向 / Column 纵向 / Grid 网格布局,不用修改子组件结构,适合横竖屏切换、布局自适应场景:
- 内置布局算法:
RowLayoutAlgorithm、ColumnLayoutAlgorithm、GridLayoutAlgorithm; - 特点:切换布局后子组件状态(输入框内容、滚动位置)保留不变;
- 限制:布局算法类用
@ObservedV2装饰,不支持 @State。
五、总结
- 简单线性排版→Column/Row;
- 多页面分类切换→Tabs+TabContent;
- 横幅滑动广告→Swiper 自动轮播;
- 不规则错落界面→RelativeContainer 相对锚定布局;
- 运行时切换多种排版→DynamicLayout 动态布局。
如有雷同,请勿追责!