当前位置: 首页 > news >正文

鸿蒙应用开发实战【22】— 空状态引导页设计与实现

鸿蒙应用开发实战【22】— 空状态引导页设计与实现

前言

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

用户首次打开号码助手时,数据库是空的——没有卡号、没有应用绑定记录。这时候如果直接展示一个空白列表,用户会感到困惑。一个好的 App 应该在空状态时展示友好的引导信息,告诉用户「这里还没有内容,接下来你可以这样做」。这就是 EmptyState 组件的价值。

本篇涵盖:EmptyState @Builder 组件设计、Blank() 弹性布局实现垂直居中、多场景空状态(列表为空/搜索无结果/筛选无匹配/导入为空)、条件渲染展示空状态、引导按钮点击导航。


图1:EmptyState 组件结构 + Blank 弹性布局 + 多场景空状态 + 条件渲染


一、EmptyState 组件设计

1.1 组件结构

// 通用的空状态组件@BuilderprivateEmptyState(icon:string,title:string,desc:string,btnText:string,btnAction:()=>void){Column(){// ① 大图标(Emoji / 自定义图标)Text(icon).fontSize(48).margin({bottom:16})// ② 标题(主要说明)Text(title).fontSize(18).fontWeight(AppFonts.WEIGHT_BOLD).fontColor(AppColors.TEXT).margin({bottom:8})// ③ 描述文案(详细说明)Text(desc).fontSize(12).fontColor(AppColors.TEXT_2).textAlign(TextAlign.Center).margin({bottom:20})// ④ 引导按钮(操作入口)Button(btnText,{type:ButtonType.Normal}).fontSize(12).fontColor('#FFFFFF').backgroundColor(AppColors.PRIMARY).borderRadius(18).height(36).width(140).onClick(()=>btnAction())}.alignItems(HorizontalAlign.Center).width('100%')}

1.2 组件层级

层级组件说明
Text(icon)大号 Emoji 图标,视觉吸引注意
Text(title)核心状态说明,粗体醒目
Text(desc)辅助引导文案
Button(btnText)CTA 按钮,点击后引导用户操作

二、Blank() 弹性布局实现垂直居中

2.1 为什么需要 Blank

空状态页面需要在屏幕中间展示,但页面上方有 TitleBar、下方有 TabBar。直接设置justifyContent(FlexAlign.Center)会让内容整体居中,但如果内容偏少可能会偏上或偏下。使用Blank()可以弹性撑开,将 EmptyState 推到视觉中心。

// 空状态页面结构Column(){// ① 标题栏(固定高度)TitleBar()// ② 弹性撑开区域Blank()// ③ 空状态内容(居中显示)this.EmptyState('📭','暂无绑定记录','你还没有添加任何应用绑定\n点击下方按钮开始添加','+ 添加应用',()=>this.navigateToAddPage())// ④ 弹性撑开区域Blank()// ⑤ 底部 TabBar(固定高度)TabBar()}.height('100%')

2.2 Blank() 的弹性原理

Blank()是一个不可见的弹性组件,会自动占据 Column 中的剩余空间。两个Blank()会把中间的 EmptyState 推到 Column 的垂直中心。

对比实现方式效果
justifyContent: Center只居中子元素内容可能偏上(TabBar 占位)
Blank() 双边撑开上下 Balance严格视觉居中

2.3 结合三态 UI

// 在实际页面中,空状态是三态 UI 的"正常内容"的一部分if(this.loading){this.LoadingState()}elseif(this.loadError){this.ErrorState(this.loadError)}elseif(this.rows.length===0){this.EmptyStatePage()// ← 这里使用 Blank + EmptyState}else{this.ContentPage()// ← 正常列表}

三、多场景空状态

不同的场景需要不同的空状态文案和图标:

3.1 场景定义

// 各个页面调用 EmptyState 的场景// 首页 — 没有绑定记录this.EmptyState('📭','暂无绑定记录','你还没有添加任何应用绑定\n点击下方按钮开始添加','+ 添加应用',()=>{this.navigate('pages/AddAppPage')})// 卡号管理 — 没有卡号this.EmptyState('💳','暂无卡号','点击右上角「+」添加你的第一张卡号','',()=>{})// 不需要按钮,右上角有 +// 搜索页 — 搜索无结果this.EmptyState('🔍','未找到匹配结果','尝试修改搜索关键词或筛选条件','',()=>{})// 粘贴导入 — 未识别到应用this.EmptyState('📎','未识别到应用信息','请确认粘贴内容包含应用名称和卡号','重新粘贴',()=>{this.pastedText=''})

3.2 场景矩阵

场景图标标题引导操作
绑定记录为空📭暂无绑定记录+ 添加应用
卡号列表为空💳暂无卡号右上角 +
搜索无结果🔍未找到匹配结果无(仅在搜索框输入)
粘贴导入为空📎未识别到应用信息重新粘贴
筛选无匹配当前筛选无结果重置筛选

四、引导按钮导航

4.1 导航封装

// 页面内部的导航方法privatenavigateToAddPage():void{router.pushUrl({url:'pages/AddAppPage',params:{}asRecord<string,Object>})}

4.2 关闭弹窗后导航

有时候空状态出现在弹窗或面板中,需要先关闭再导航:

privatehandleAction():void{if(this.isInSheet){this.showSheet=false// 先关闭面板}// 延迟导航,给关闭动画留时间setTimeout(()=>{this.navigateToAddPage()},300)}

五、本篇小结

知识点核心要点
EmptyState @Builder参数化:icon/title/desc/btnText/btnAction
Blank() 弹性布局两个 Blank() 将内容推到垂直居中
多场景复用搜索/列表/导入/筛选各自定制文案
条件渲染if/else 判断数据长度为 0 时展示空状态
引导按钮点击导航到添加页面,考虑弹窗延迟

参考资料

  • 鸿蒙应用开发实战【23】— 三态 UI
  • 鸿蒙应用开发实战【05】— 首页开发与状态管理
  • Blank 组件 API
  • @Builder 装饰器
  • Column 容器

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

  • 开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
  • Blank 组件文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-blank
  • Column 容器文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-column
http://www.jsqmd.com/news/1197459/

相关文章:

  • RA6M4开发板CTSU触摸技术开发指南
  • 从零构建随机森林:Bagging到实战手写数字识别
  • 电容特性与应用全解析:从基础原理到电路设计
  • GPT-5.6与Blender MCP集成:自然语言驱动3D建模实战
  • 【FPGA】从零到一:基于QuestaSim的Vivado DDR3仿真平台搭建与调试实战
  • GPT 5.6 Ultra模式并行Sub-agent技术解析与实战应用
  • Multisim光控路灯电路设计:从光敏电阻到滞回比较器实战
  • 2026年7月微软笔记本开机闪一下断电取机检查|多次冷启动、持续供电和负载切换与全国门店|检测:启动电流、供电保护、短路和温度信号;验收:多次冷启动、持续供电和负载切换 - 笔记本专业售后
  • 微信小程序支付回调与沙箱测试:从配置到避坑的实战指南
  • 学习OpenMV(二)I/O实战:从引脚分配到传感器交互
  • 从零构建8位RISC CPU:基于FSM的Verilog控制器设计实战
  • 从FIS到HDL:基于Matlab/Simulink的模糊控制器硬件代码自动生成实践
  • SQ-1魔方复原全攻略:从复形到对色的完整教程
  • Windows鼠标指针主题定制:从安装部署到批量管理全攻略
  • 【LVGL】LVGL8.1 GIF库深度配置与性能调优指南
  • 从机械到电子:电子凸轮核心原理与典型应用场景解析
  • Morpheus基准:大语言模型持续学习能力评估框架详解
  • ESP32实战:MPU6050 DMP姿态解算与OLED显示
  • iOS 18 SpeechAnalyzer API:设备端语音识别与实时转录技术解析
  • JDK11 从零部署指南:下载、安装、JRE生成与环境变量一键配置
  • Opus-4.7与GPT-5.5-Pro实测对比:AI模型选型实战指南
  • Ubuntu系统下VS Code的三种主流安装方式与配置实践
  • 锤石下路优势攻略:技能连招、兵线管理与团战定位详解
  • 2026 年更新:小金靠谱的酒店设备回收厂商哪家好,揭秘酒店设备回收背后的惊人利润密码 - 企业推荐官【认证】
  • [运算放大器系列]三、4-20mA电流环变送器电路设计与抗干扰分析
  • 单片机IO的三种面孔:推挽、开漏与高阻态的实战选择
  • Python列表remove()函数实战避坑指南
  • 2026 最新 Codex Dream Skin 发布!Codex 桌面版完整换肤方案,无需修改 app.asar,支持升级恢复,一键安装
  • Python 如何选择与使用不同版本的UUID
  • Spring Security 6.x实战:构建可复用的用户认证授权模块