ArkTS(鸿蒙 ArkUI)宿舍底部 Tab 页面代码完整解析
一、整体项目说明
这份代码是HarmonyOS ArkTS 声明式 UI页面,实现底部 4 标签导航(首页 / 推荐 / 发现 / 我的)宿舍管理页面:
- 页面入口:
/pages/DormTabPage,由@Entry标记为应用页面; - 核心能力:点击底部 Tab 切换不同内容区域,4 个页面分别使用
Swiper轮播、Grid网格、普通文本、个人中心; - 状态驱动:用
@State装饰器变量currentIndex控制页面切换,点击 Tab 修改索引,UI 自动刷新。
二、逐段代码拆解讲解
1. 页面头部装饰器与结构体定义
@Entry @Component struct DormTabPage{ @State currentIndex: number = 0 //0首页、1推荐、2发现、3我的@Entry:标识当前结构体是独立页面,系统可路由跳转渲染;@Component:标识自定义 UI 组件,必须实现build()方法构建界面;@State currentIndex: number = 0@State:状态装饰器,变量变化时页面自动重绘;currentIndex:Tab 选中索引,默认 0(首页激活);- 映射规则:0 = 首页,1 = 推荐,2 = 发现,3 = 我的。
2. build () 根布局整体结构
build(){ Column(){ // 上方内容区域(动态切换4个页面) Column(){ // 4组if判断,根据currentIndex渲染对应页面 // 1.首页 if(this.currentIndex === 0){ ... } // 2.推荐页 if(this.currentIndex === 1){ ... } // 3.发现页 if(this.currentIndex === 2){ ... } // 4.我的页面 if(this.currentIndex === 3){ ... } } .flexGrow(1) // 关键:占满剩余高度,把底部导航挤到屏幕最下方 // 底部Tab导航栏 Row(){ Text("首页")... Text("推荐")... Text("发现")... Text("我的")... } .width('100%') .height(55) .border({width:{top:1},color:'#cccccc'}) } .width('100%') .height('100%') }布局逻辑:
- 根容器
Column:垂直布局,占满全屏宽高; - 上方内容容器
Column添加.flexGrow(1):自动填充屏幕剩余高度,底部导航栏固定在页面底部; - 下方
Row水平容器:承载 4 个 Tab 文字,统一高度 55,顶部加灰色分割线区分内容区。
三、4 个页面内容模块详解
模块 1:首页(currentIndex=0)—— Swiper 舍友轮播
if(this.currentIndex === 0){ Column(){ Text('517宿舍') .fontSize(24) .fontWeight(FontWeight.Bold) .margin({top:20,bottom:20}) Swiper(){ // 轮播项1 Text(`舍友1:王五\n学号:2025001`) .width('100%') .height(180) .backgroundColor('#E8F4FD') .fontSize(20) .textAlign(TextAlign.Center) // 轮播项2 Text(`舍友2:李四\n学号:2025002`) .width('100%') .height(180) .backgroundColor('#FFF3E0') .fontSize(20) .textAlign(TextAlign.Center) // 轮播项3 Text(`舍友3:王五\n学号:2025003`) .width('100%') .height(180) .backgroundColor('#E7F5E9') .fontSize(20) .textAlign(TextAlign.Center) } .width('92%') .height(180) .indicator(true) // 开启轮播底部小圆点指示器 } }功能说明:
Swiper:鸿蒙轮播组件,内部每一个子组件为一页滑动卡片;.indicator(true):显示分页圆点,当前页面蓝色高亮;- 三张卡片分别展示 3 位舍友信息,不同浅底色区分;
- 顶部标题「517 宿舍」加粗,上下外边距 20。
模块 2:推荐页(currentIndex=1)—— Grid 6 宫格宿舍信息
if(this.currentIndex === 1){ Column(){ Text('推荐页-宿舍信息格子') .fontSize(24) .fontWeight(FontWeight.Bold) .margin({top:20,bottom:30}) Grid(){ ForEach([1,2,3,4,5,6], (item:number)=>{ GridItem(){ Text(`信息${item}`) .width('90%') .height(90) .border({width:1,color:Color.Black}) .textAlign(TextAlign.Center) .fontSize(18) } }) } .columnsTemplate('1fr 1fr 1fr') // 3列均分宽度 .width('90%') } }核心知识点:
Grid网格容器 +GridItem网格项:实现多列格子布局;.columnsTemplate('1fr 1fr 1fr'):设置 3 列,每列宽度均等(fr = 剩余空间均分);ForEach:循环渲染数组,快速生成 6 个格子,无需重复写 6 遍 Text;- 每个格子黑色边框,高度 90,居中显示文字。
模块 3:发现页(currentIndex=2)—— 静态介绍文本
if(this.currentIndex === 2){ Column(){ Text("欢迎来到新517宿舍,\n下面介绍一下宿舍信息。") .fontSize(22) .margin({top:40}) } }最简单页面,仅居中展示一段介绍文案,\n实现文字换行,顶部外边距 40。
模块 4:我的页面(currentIndex=3)—— 个人中心占位
if(this.currentIndex === 3){ Column(){ Text('我的页面') .fontSize(24) } }预留个人中心页面,仅标题占位,可后续拓展头像、姓名、宿舍信息、设置等功能。
四、底部 Tab 导航栏完整逻辑(核心切换交互)
Row(){ // Tab1 首页 Text('首页') .fontSize(17) // 三元表达式:选中索引=0时蓝色,否则黑色 .fontColor(this.currentIndex===0?Color.Blue:Color.Black) .flexGrow(1) // 4个Tab均分一行宽度 .textAlign(TextAlign.Center) // 点击切换索引,触发页面刷新 .onClick(()=>this.currentIndex=0) // Tab2 推荐 Text('推荐') .fontSize(17) .fontColor(this.currentIndex===1?Color.Blue:Color.Black) .flexGrow(1) .textAlign(TextAlign.Center) .onClick(()=>this.currentIndex=1) // Tab3 发现 Text('发现') .fontSize(17) .fontColor(this.currentIndex===2?Color.Blue:Color.Black) .flexGrow(1) .textAlign(TextAlign.Center) .onClick(()=>this.currentIndex=2) // Tab4 我的 Text('我的') .fontSize(17) .fontColor(this.currentIndex===3?Color.Blue:Color.Black) .flexGrow(1) .textAlign(TextAlign.Center) .onClick(()=>this.currentIndex=3) } .width('100%') .height(55) .border({width:{top:1},color:'#cccccc'})交互与样式关键点:
.flexGrow(1):4 个 Text 平分Row整行宽度,均匀分布底部;- 文字颜色三元判断:匹配
currentIndex则蓝色高亮,未选中黑色; .onClick(()=>this.currentIndex=X):点击修改状态变量,@State自动触发页面重绘,上方if判断渲染对应页面;- 整体高度 55,顶部灰色边框,和上方内容区分,模拟 App 底部导航栏标准样式。
五、代码整体运行流程
- 页面初始化:
currentIndex=0,默认渲染首页 Swiper 轮播,底部「首页」文字蓝色; - 用户点击底部「推荐」:执行
onClick修改currentIndex=1; @State检测变量变化,页面重新执行build();if(this.currentIndex === 1)成立,渲染 Grid6 宫格,「推荐」文字变蓝;- 点击「发现 / 我的」同理,切换对应页面内容与 Tab 高亮。
六、用到的 ArkUI 核心组件总结
表格
| 组件 | 用途 |
|---|---|
| Column | 垂直线性布局 |
| Row | 水平线性布局 |
| Text | 文字展示 |
| Swiper | 滑动轮播图 |
| Grid + GridItem | 网格多列布局 |
| ForEach | 列表循环渲染 |
| @State | 响应式状态管理 |
| flexGrow | 弹性占满剩余空间 |
| onClick | 点击事件绑定 |
七、优化拓展建议(可选)
- 抽离复用 Tab 组件:4 个 Tab 代码重复,可封装自定义 TabItem 组件减少冗余;
- 数据抽离:舍友信息、Grid 格子数据提取到数组变量,避免写死在 UI 内;
- 添加图标:Tab 搭配
Image图标,做成图文导航(主流 App 底部 Tab 样式); - 动画过渡:页面切换添加
animateTo过渡动画,切换更顺滑; - 拆分页面:4 个页面拆分为独立子组件,
build()代码更简洁。
ArkTS @State 响应式变量 + TextInput 双向绑定完整代码详解
一、页面整体概述
页面路径:/pages/StatesDemo3,核心演示 **@State 响应式状态管理 ** 与TextInput输入框双向数据绑定:
- 定义
@State字符串变量存储输入内容; - 输入框实时捕获用户输入,同步更新状态变量;
- 上方 Text 文字实时同步展示输入框内容,输入文字变化,文字立刻刷新。 信心指数:10 分,全部为鸿蒙 ArkUI 标准状态管理语法,无推测内容。
二、头部装饰器与响应式变量定义
@Entry @Component struct StatesDemo3{ // 响应式状态变量:存储输入框文本,初始为空字符串 @State inputText:string = ""@Entry:标记当前结构体是独立页面,可直接路由加载;@Component:自定义 UI 组件标识,必须实现build()渲染界面;@State inputText:string = ""@State:响应式装饰器,核心作用:变量发生修改时,页面自动重新渲染,所有使用该变量的 UI 同步更新;inputText:字符串类型,专门用来接收、保存 TextInput 输入的文字;- 初始值为空字符串
"",页面刚打开时无输入内容。
三、build () 根布局整体结构
build() { Column({space:20}){ // 实时展示输入内容的文本 Text(`你输入的内容是: ${this.inputText}`) .fontSize(26) // 文本输入框 TextInput({text:this.inputText, placeholder:"请输入任意内容"}) .width('100%') .height(50) .padding({left:20}) .onChange((value: string) => { this.inputText = value }) } .width('100%') .height('100%') .padding(30) }根容器 Column 全局配置
Column({space:20}){ ... } .width('100%') .height('100%') .padding(30)Column({space:20}):垂直布局,文字与输入框上下间距 20vp;- 宽高
100%铺满手机屏幕; .padding(30):页面四周预留 30 像素内边距,组件不贴屏幕边缘。
四、分模块逐段拆解代码
模块 1:实时回显文本 Text
Text(`你输入的内容是: ${this.inputText}`) .fontSize(26)- 模板字符串
`...${变量}`:反引号语法,可直接嵌入结构体变量; ${this.inputText}:读取@State响应式变量,实时展示输入内容;- 核心效果:只要
inputText变量被修改,这段文字会自动刷新,无需手动重绘页面; - 字号 26,放大文字方便查看回显效果。
模块 2:核心输入框 TextInput(双向绑定逻辑)
TextInput({text:this.inputText, placeholder:"请输入任意内容"}) .width('100%') .height(50) .padding({left:20}) .onChange((value: string) => { this.inputText = value })1. TextInput 构造入参
text:this.inputText:输入框绑定状态变量,实现数据流向 UI;placeholder:"请输入任意内容":输入框空白时显示灰色提示文字。
2. 样式修饰器
.width('100%'):输入框占满父容器全部宽度;.height(50):固定输入框高度 50vp;.padding({left:20}):输入文字距离左侧边框 20 像素,避免文字贴边。
3. .onChange 回调(UI 流向数据)
.onChange((value: string) => { this.inputText = value })- 用户每输入 / 删除一个字符,触发
onChange回调; value为输入框当前最新完整文本;- 将最新文本赋值给
this.inputText响应式变量,完成数据同步。
五、双向绑定完整数据流(核心原理)
- 数据 → UI(text 绑定)
text:this.inputText:变量的值会同步显示在输入框内; - UI → 数据(onChange)用户打字触发
onChange,把输入内容赋值给inputText; - @State 自动刷新
inputText发生变化后,页面自动重绘,上方 Text 读取最新变量值,实现实时回显。
运行流程示例:
- 页面初始化:
inputText = "",上方文字仅显示「你输入的内容是:」; - 在输入框输入
hello; onChange捕获value="hello",执行this.inputText = "hello";@State检测变量变更,页面刷新,上方文字变为「你输入的内容是: hello」;- 删除文字,变量同步清空,文字同步消失。
六、核心知识点:@State 响应式变量对比普通变量
- 普通成员变量(无 @State)修改变量后,页面 UI 不会自动更新,文字不会同步变化;
- @State 修饰变量变量变更 → 页面自动重渲染 → 所有引用该变量的组件同步刷新; 本案例是表单输入、实时回显最基础的标准写法。
七、代码拓展优化建议
- 限制输入长度给 TextInput 添加
.maxLength(20),限制最多输入 20 个字符; - 输入类型区分手机号输入添加
.type(InputType.PhoneNumber),数字输入键盘; 密码输入.type(InputType.Password)隐藏明文; - 清空按钮新增 Button,点击执行
this.inputText = ""一键清空输入框; - 输入校验在
onChange内增加判断,过滤空格、特殊字符; - 多输入框联动新增第二个 TextInput,共用同一个
@State变量,实现多输入框同步内容。
八、本页面用到的 ArkUI 组件 & API 汇总
表格
| 语法 / 组件 | 功能说明 |
|---|---|
| @Entry | 页面入口装饰器 |
| @Component | UI 组件装饰器 |
| @State | 响应式状态装饰器,驱动 UI 自动刷新 |
| Column | 垂直布局容器 |
| Text | 文字展示,实时回显输入内容 |
| TextInput | 文本输入框,接收用户输入 |
${this.变量} | 模板字符串变量插值 |
| onChange() | 输入框内容变更监听回调 |
| placeholder | 输入框空白提示文字 |
| padding / width / height | 组件尺寸与内边距样式 |
ArkTS Swiper 轮播图完整代码详解
一、页面整体概述
页面路径:/pages/SwiperDemo,核心实现图片自动轮播组件 Swiper,搭配数组 + ForEach 循环批量渲染校园图片轮播,完整包含指示器、自动播放、循环滚动、轮播间隔等常用配置。 页面结构:顶部学院标题 + 图片轮播模块,整体垂直布局,四周预留内边距。 信心指数:10 分,全部为鸿蒙 ArkUI 官方标准 Swiper、ForEach 数组渲染语法,无推测内容。
二、头部装饰器与图片数组定义
@Entry @Component struct SwiperDemo{ // 私有图片资源数组,存储3张本地图片资源 private abcList:Resource[]=[ $r('app.media.abc0'), $r('app.media.abc1'), $r('app.media.abc2') ]@Entry:标记为独立页面入口;@Component:自定义 UI 组件,必须实现build()渲染界面;private abcList:Resource[]private:私有成员,仅当前页面内可访问;Resource[]:资源类型数组,专门存放图片 / 媒体资源;$r('app.media.xxx'):读取项目resources/base/media目录下的本地图片;- 数组内存放 3 张校园图片,供下方 ForEach 循环遍历渲染轮播项。
三、build () 根布局整体结构
build(){ Column(){ // 页面标题 Text('欢迎来到河北软件职业技术学院') .fontSize(30) .fontWeight(FontWeight.Bolder) // 核心轮播Swiper Swiper(){ ForEach(this.abcList,(item:Resource)=>{ Image(item) .objectFit(ImageFit.Cover) }) } .width('100%') .height(180) .indicator(true) .autoPlay(true) .interval(3000) .loop(true) } .padding(10) }根容器 Column 配置
Column垂直布局,标题与轮播图上下排列;.padding(10):页面整体四周预留 10 像素内边距,组件不贴屏幕边缘。
四、分模块逐段拆解代码
模块 1:页面标题文本
Text('欢迎来到河北软件职业技术学院') .fontSize(30) .fontWeight(FontWeight.Bolder)字号 30、超粗字体,作为页面主标题,自动与下方 Swiper 保留默认间距。
模块 2:Swiper 轮播容器 + ForEach 循环渲染(核心)
Swiper(){ // 循环遍历图片数组,批量生成轮播图片 ForEach(this.abcList,(item:Resource)=>{ Image(item) .objectFit(ImageFit.Cover) }) } // Swiper全局配置修饰器 .width('100%') .height(180) .indicator(true) .autoPlay(true) .interval(3000) .loop(true)1. ForEach 数组循环渲染
ForEach(this.abcList,(item:Resource)=>{ Image(item).objectFit(ImageFit.Cover) })ForEach(数组, (单条数据)=>{渲染组件}):ArkTS 列表循环语法;- 依次取出数组里 3 张图片资源,每一张生成一个 Image,作为 Swiper 的一页轮播内容;
objectFit(ImageFit.Cover):图片等比例铺满轮播容器,超出区域自动裁剪,不变形留白。
2. Swiper 全部配置修饰器详解
表格
| 修饰器 | 功能说明 |
|---|---|
.width('100%') .height(180) | 轮播宽度铺满屏幕,固定高度 180vp |
.indicator(true) | 开启底部分页小圆点指示器,标识当前第几页 |
.autoPlay(true) | 开启自动轮播,无需手动滑动 |
.interval(3000) | 自动轮播切换间隔,单位毫秒,3000=3 秒切换一张 |
.loop(true) | 开启无限循环,滑到最后一张后自动切回第一张,不会终止 |
五、页面完整运行流程
- 页面初始化,读取
abcList数组内 3 张校园图片; - ForEach 循环批量生成 3 张 Image,放入 Swiper 轮播容器;
- 页面加载完成后,自动开启轮播:每 3 秒切换一张图片;
- 底部显示 3 个小圆点指示器,当前页面圆点高亮;
- 滑动到最后一张图片后,自动无缝切回第一张,无限循环播放。
六、核心知识点讲解
1. Swiper 轮播组件使用场景
首页 Banner、校园海报、商品轮播、图片相册,是 App 首页最常用组件。
2. ForEach 循环优势
无需手动重复写 3 次 Image 组件,新增 / 删除图片只需修改abcList数组,代码复用、易维护。
3. Resource 资源数组
统一管理图片资源,适合批量图片场景,区分于单张图片单独引用。
4. ImageFit.Cover 图片适配
保证图片填满轮播框,不会拉伸变形,是 Banner 轮播标准适配方案。
七、拓展优化建议
- 自定义指示器样式添加
indicatorStyle()修改圆点大小、颜色、间距; - 手动控制轮播搭配
SwiperController实现上一页 / 下一页按钮手动切换; - 轮播停止逻辑页面失去焦点时关闭 autoPlay,节省性能;
- 图片点击事件给 Image 添加
.onClick(),点击轮播图跳转详情页面; - 动态数组结合
@State修饰数组,实现网络请求动态加载轮播图片。
八、本页面用到的 ArkUI 组件 & API 汇总
表格
| 组件 / 语法 | 功能 |
|---|---|
| Swiper | 滑动轮播容器 |
| ForEach | 数组循环批量渲染组件 |
| Image | 图片展示组件 |
| Column | 垂直布局容器 |
| Text | 页面标题文字 |
| Resource[] | 图片资源数组类型 |
| $r('app.media') | 读取本地 media 图片资源 |
| indicator() | 开启 / 关闭分页指示器 |
| autoPlay() | 自动播放开关 |
| interval() | 自动切换时间间隔 |
| loop() | 无限循环开关 |
| objectFit(ImageFit.Cover) | 图片填充适配模式 |