鸿蒙应用开发实战【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