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

【鸿蒙原生应用开发实战】第四篇:详情页与收藏交互 — 动态数据切换与用户交互设计

【鸿蒙原生应用开发实战】第四篇:详情页与收藏交互 — 动态数据切换与用户交互设计

前言

详情页是内容型App中最关键的页面,它承载着对内容的深度展示和用户交互。在"宇宙探索"App中,DetailPage不仅要展示8个天体的详细数据,还要处理收藏交互、路由传参、动态数据切换等复杂逻辑。

本篇你将学到:

  • 路由参数接收与动态数据加载
  • 信息网格布局设计
  • 收藏按钮的状态切换
  • 趣味知识模块展示
  • 从详情页返回的数据一致性

一、页面功能总览

DetailPage包含以下内容模块:

模块内容实现方式
顶部返回← 返回按钮router.back()
天体名称区中文名 + 英文名 + 类型标签垂直居中布局
描述区天体详细文字描述多行文本
基本信息质量/直径/距离/温度2×2 网格卡片
趣味知识一个冷知识特殊底色区块
收藏按钮收藏/取消收藏@State 状态切换

二、完整代码实现

2.1 InfoItem 组件

importrouterfrom'@ohos.router';import{CelestialData,CELESTIAL_LIST,FavoriteManager}from'../model/CelestialData';@Componentstruct InfoItem{label:string='';value:string='';build(){Column(){Text(this.value).fontSize($r('app.float.app_small_size')).fontColor($r('app.color.app_color_white')).fontWeight(FontWeight.Bold);Text(this.label).fontSize($r('app.float.app_caption_size')).fontColor($r('app.color.app_color_text_secondary')).margin({top:4});}.width('45%').padding(12).backgroundColor('rgba(255, 255, 255, 0.05)').borderRadius(10).alignItems(HorizontalAlign.Center);}}

设计解读

  • width('45%')— 两个 Item 并排布局,留出10%间隔
  • 半透明白色背景rgba(255,255,255,0.05)— 卡片感但不抢眼
  • 值大标题、标签小字 — 对比强化阅读层次

2.2 接口定义

interfaceInfoPair{label:string;value:string;}

这个接口在文件末尾定义(不在@Component内),用于infoItems数组的类型声明。

2.3 详情页主组件

@Entry@Componentstruct DetailPage{@Statedata:CelestialData={id:0,name:'',englishName:'',type:'',description:'',mass:'',diameter:'',distance:'',temperature:'',fact:'',color:'#FFFFFF',isFavorite:false};@StateisFav:boolean=false;@StateinfoItems:InfoPair[]=[];aboutToAppear():void{// 1. 从路由参数获取天体IDconstparams=router.getParams()asRecord<string,Object>;if(params&&params['id']!==undefined){constid=Number(params['id']);// 2. 遍历数据源找到对应天体for(leti=0;i<CELESTIAL_LIST.length;i++){if(CELESTIAL_LIST[i].id===id){this.data=CELESTIAL_LIST[i];break;}}}// 3. 检查收藏状态this.isFav=FavoriteManager.isFavorite(this.data.id);// 4. 组装信息条目this.infoItems=[{label:'质量',value:this.data.mass},{label:'直径',value:this.data.diameter},{label:'距地距离',value:this.data.distance},{label:'温度',value:this.data.temperature}];}toggleFav():void{this.isFav=FavoriteManager.toggle(this.data.id);this.data.isFavorite=this.isFav;}build(){Column(){Scroll(){Column(){// ===== 顶部返回 =====Row(){Text('←').fontSize(24).fontColor($r('app.color.app_color_white')).onClick(()=>{router.back();});}.width('100%').padding({left:16,top:12});// ===== 天体名称区域 =====Column(){Text(this.data.name).fontSize(48).fontColor($r('app.color.app_color_white')).fontWeight(FontWeight.Bold);Text(this.data.englishName).fontSize($r('app.float.app_body_size')).fontColor($r('app.color.app_color_text_secondary')).margin({top:8});Text(this.data.type).fontSize($r('app.float.app_small_size')).fontColor(this.data.color).padding({left:16,right:16,top:4,bottom:4}).backgroundColor('rgba(255, 255, 255, 0.08)').borderRadius(20).margin({top:12});}.width('100%').padding({top:20,bottom:24}).alignItems(HorizontalAlign.Center);// ===== 描述 =====Text(this.data.description).fontSize($r('app.float.app_body_size')).fontColor($r('app.color.app_color_white')).lineHeight(24).padding({left:16,right:16});// ===== 基本信息(2×2网格) =====Text('基本信息').fontSize($r('app.float.app_body_size')).fontColor($r('app.color.app_color_accent')).fontWeight(FontWeight.Bold).width('100%').padding({left:16,top:24,bottom:12});Row(){ForEach(this.infoItems,(item:InfoPair)=>{InfoItem({label:item.label,value:item.value})},(item:InfoPair)=>item.label)}.width('100%').padding({left:16,right:16}).justifyContent(FlexAlign.SpaceBetween);// ===== 趣味知识 =====Text('✨ 趣味知识').fontSize($r('app.float.app_body_size')).fontColor($r('app.color.app_color_accent')).fontWeight(FontWeight.Bold).width('100%').padding({left:16,top:24,bottom:12});Text(this.data.fact).fontSize($r('app.float.app_small_size')).fontColor($r('app.color.app_color_white')).lineHeight(22).padding({left:16,right:16,top:12,bottom:12}).backgroundColor('rgba(255, 215, 0, 0.06)').borderRadius(12).margin({left:16,right:16,bottom:24});// ===== 收藏按钮 =====Button(){Text(this.isFav?'★ 已收藏':'☆ 收藏').fontSize($r('app.float.app_body_size')).fontColor($r('app.color.app_color_white'));}.width('80%').height(48).backgroundColor(this.isFav?'#FF6B6B':'#0F3460').borderRadius($r('app.float.app_button_radius')).margin({top:12,bottom:32}).onClick(()=>{this.toggleFav();});}.width('100%');}.layoutWeight(1);}.width('100%').height('100%').backgroundColor($r('app.color.app_color_background'));}}

三、关键技术点解析

3.1 路由参数接收与动态数据加载

这是详情页最核心的机制——根据不同的路由参数展示不同天体的数据

参数传递(发送端)

// 从首页热门卡片跳转router.pushUrl({url:'pages/DetailPage',params:{id:this.item.id}});// 从首页每日天文区跳转(固定展示地球)router.pushUrl({url:'pages/DetailPage',params:{id:4}});// 从收藏列表跳转router.pushUrl({url:'pages/DetailPage',params:{id:item.id}});

参数接收与数据匹配(接收端)

aboutToAppear():void{constparams=router.getParams()asRecord<string,Object>;if(params&&params['id']!==undefined){constid=Number(params['id']);// 线性查找匹配的天体for(leti=0;i<CELESTIAL_LIST.length;i++){if(CELESTIAL_LIST[i].id===id){this.data=CELESTIAL_LIST[i];break;}}}// 初始化收藏状态this.isFav=FavoriteManager.isFavorite(this.data.id);// 组装信息条目this.infoItems=[{label:'质量',value:this.data.mass},{label:'直径',value:this.data.diameter},{label:'距地距离',value:this.data.distance},{label:'温度',value:this.data.temperature}];}

数据流链路

用户点击卡片 → router.pushUrl({ params: { id: N } }) → DetailPage.aboutToAppear() → 读取 params.id → CELESTIAL_LIST 中查找 id === N → this.data = 匹配到的天体数据 → UI 自动刷新展示该天体

3.2 @State 状态管理的双重绑定

在这个页面中有三个@State变量:

@Statedata:CelestialData;// 当前展示的天体数据@StateisFav:boolean;// 收藏状态的开关@StateinfoItems:InfoPair[];// 信息条目列表

每个变量的变化都会触发对应 UI 的重新渲染:

@State 变量变更时机影响UI
dataaboutToAppear()从路由参数加载名称、描述、基本信息、趣味知识全部刷新
isFavtoggleFav()用户点击收藏按钮文字(★已收藏/☆收藏)和颜色
infoItemsaboutToAppear()初始化时组装四个 InfoItem 卡片

3.3 收藏按钮的状态切换

toggleFav():void{this.isFav=FavoriteManager.toggle(this.data.id);this.data.isFavorite=this.isFav;}

这短短两行做了三件事:

  1. 调用FavoriteManager.toggle(id)— 修改数据层,添加或移除收藏
  2. this.isFav = 返回值@State变量变化,触发UI刷新收藏按钮
  3. 同步到this.data.isFavorite— 保持数据对象一致性,防止页面间数据不同步

按钮视觉反馈

状态文字背景色含义
未收藏☆ 收藏#0F3460(深蓝)点击即可收藏
已收藏★ 已收藏#FF6B6B(红色)点击取消收藏

3.4 类型标签的专属色

天体类型标签使用了该天体的专属颜色:

Text(this.data.type).fontColor(this.data.color)

这意味着:

  • 太阳(恒星)→#FF6B35橙色标签
  • 地球(行星)→#4B7B8A蓝绿色标签
  • 银河系(星系)→#6B8EC4蓝色标签
  • 猎户座大星云(星云)→#FF69B4粉色标签

每个标签还加上了胶囊背景

.backgroundColor('rgba(255, 255, 255, 0.08)').borderRadius(20)

半透明背景让标签看起来更"立体",borderRadius(20)制造胶囊圆角效果。

3.5 趣味知识模块

Text(this.data.fact).fontSize($r('app.float.app_small_size')).fontColor($r('app.color.app_color_white')).lineHeight(22).backgroundColor('rgba(255, 215, 0, 0.06)')// 极淡金色背景.borderRadius(12)

趣味知识模块用三个细节区别于普通内容:

  • 淡金色背景rgba(255, 215, 0, 0.06)— 暗示"知识亮点"
  • ✨ 前缀— 段落标题前的emoji,增加趣味性
  • 适中行高lineHeight(22)— 确保长文本可读性

四、信息网格布局详解

4.1 2×2 网格的实现

Row(){ForEach(this.infoItems,(item:InfoPair)=>{InfoItem({label:item.label,value:item.value})},(item:InfoPair)=>item.label)}.width('100%').padding({left:16,right:16}).justifyContent(FlexAlign.SpaceBetween);

infoItems数组有4项,ForEach 会渲染4个InfoItem

  • 每个InfoItem宽度45%→ 一行放2个 → 两行正好4个
  • SpaceBetween自动在元素之间分配空间

4.2 InfoItem 组件的细节

Column(){Text(this.value)// 值(大号、白色、加粗)Text(this.label)// 标签(小号、灰色)}.width('45%').backgroundColor('rgba(255, 255, 255, 0.05)')// 半透明白色底.borderRadius(10).alignItems(HorizontalAlign.Center);

这个组件体现了视觉层次的设计原则:

  • 值比标签大两号(small_size: 14fpvscaption_size: 12fp
  • 值是白色,标签是灰色,主次分明
  • 值加粗,标签不加粗
  • 半透明背景营造卡片感

五、页面间数据一致性

5.1 从详情页返回后列表页刷新收藏状态

这是一个常见的跨页面数据同步问题。用户在详情页收藏/取消收藏后,返回列表页时需要看到最新的收藏状态。

实现方案

FavPageCelestialPage中使用onPageShow生命周期钩子:

// FavPage.ets — 收藏列表页onPageShow():void{this.loadFavorites();// 每次显示都重新加载收藏数据}// CelestialPage.ets — 天体列表页onPageShow():void{this.applyFilter();// 重新应用筛选,刷新收藏状态}

流程

DetailPage 中收藏/取消收藏 → router.back() → 返回到 FavPage / CelestialPage → onPageShow() 被触发 → 重新从 FavoriteManager 读取最新数据 → @State 更新 → UI 刷新

5.2 router.back() 的正确使用

// 详情页的返回按钮Text('←').onClick(()=>{router.back();// 返回上一页});

router.back()不需要传参,框架会自动返回到跳转到当前页的上一页。

路由栈示意图

Index → CelestialPage → DetailPage ↓ back() CelestialPage ← onPageShow() 触发刷新 收藏列表页: FavPage → DetailPage ↓ back() FavPage ← onPageShow() 触发刷新

六、完整页面展示效果

以"地球"为例,DetailPage的展示效果:

┌──────────────────────────────┐ │ ← │ │ │ │ 地 球 │ │ Earth │ │ ┌──────┐ │ │ │ 行星 │ │ │ └──────┘ │ │ │ │ 地球是太阳系中唯一已知存在 │ │ 生命的行星,拥有液态水和 │ │ 适宜的大气层... │ │ │ │ 基本信息 │ │ ┌──────────┐ ┌──────────┐ │ │ │ 5.972×10²⁴│ │ 12,742km │ │ │ │ 质量 │ │ 直径 │ │ │ └──────────┘ └──────────┘ │ │ ┌──────────┐ ┌──────────┐ │ │ │1.496亿km │ │ 平均15°C │ │ │ │ 距地距离 │ │ 温度 │ │ │ └──────────┘ └──────────┘ │ │ │ │ ✨ 趣味知识 │ │ ┌──────────────────────────┐ │ │ │ 地球是太阳系中密度最大 │ │ │ │ 的行星。约71%的表面被水 │ │ │ │ 覆盖,被称为"蓝色星球"。 │ │ │ └──────────────────────────┘ │ │ │ │ ┌────────────────┐ │ │ │ ☆ 收藏 │ │ │ └────────────────┘ │ └──────────────────────────────┘

七、本篇总结

本片完成了DetailPage详情页的完整开发,核心收获:

  1. 动态数据加载— 通过路由参数id动态切换展示不同天体的详细数据
  2. 信息网格布局— 2×2 网格展示质量/直径/距离/温度四维信息
  3. 收藏交互— 按钮状态切换的完整实现,数据层+UI层联动
  4. 趣味知识模块— 特殊视觉样式的知识点展示区块
  5. 页面间数据一致性router.back()+onPageShow()确保返回时列表页刷新
  6. InfoItem 组件复用— 可复用的信息卡片组件设计

下篇预告:最后一篇我们将完成FavPage(收藏列表页)和ProfilePage(个人中心页),包含收藏管理、空状态设计、旅行统计、功能菜单等完整功能。


本篇涉及的文件

  • entry/src/main/ets/pages/DetailPage.ets— 详情页主组件
  • entry/src/main/ets/model/CelestialData.ets— 数据源与收藏管理
http://www.jsqmd.com/news/1014015/

相关文章:

  • 2026年6月市场比较好的真空计公司推荐,真空泵/真空计/氦质谱检漏仪,真空计销售商哪家好 - 品牌推荐师
  • MPC8260 SCC HDLC模式硬件加速机制与嵌入式通信实战
  • 2026 滨海新区靠谱整装精选指南 本地高口碑装修公司推荐 - 资讯速览
  • 深入解析PowerPC SPR:从编码机制到缓存与性能监控实战
  • 零代码构建AI工作流:Awesome-Dify-Workflow让每个人都能成为AI应用开发者
  • 药企QC科室私藏效率工具清单 - lcs
  • 2026降AIGC革命:AI率92%暴降至5%!实测10款降AI率平台!免费降AIGC额度薅到爽!
  • 本地Cookie管理革命:Get cookies.txt LOCALLY 如何重新定义你的浏览器隐私安全
  • MPC8540 DMA控制器:从寄存器到跨步传输的嵌入式数据搬运实战
  • 【Agent Harness实战】我给我的Agent系统请了八个“保洁阿姨”,让AI自己整理自己
  • 高效获取B站高质量视频:downkyi哔哩下载姬专业应用指南
  • 谷歌DeepMind报告:AGI只是起点,从AGI到ASI有四条路径,但面临六道“墙”!
  • 深蓝词库转换技术架构深度解析:打破输入法生态壁垒的工程实践
  • 微信免费PDF转图片全攻略:3款零下载工具实测+保姆级教程 - 时时资讯
  • 如何在通达信中快速部署缠论指标:5分钟完成专业级技术分析
  • 2026年度10款降AI率软件红黑榜!优缺点全透明,达标率对标顶级水准
  • 2026青岛海鲜最新防坑地图:黄岛金沙滩游玩,为什么一定要去这家「金沙渔府」? - 资讯速览
  • 如何快速配置洛雪音乐音源:免费获取全网无损音乐的完整解决方案
  • 从Dijkstra到TEB:为你的ROS机器人选对路径规划算法(含A*、DWA对比实测)
  • 【双MCU项目复盘与优化】02 -自定义串口通信协议
  • MPC8280内存控制器与L2缓存接口设计详解
  • 从DCNv1到v3:手把手带你用MMDetection/YOLO跑通可变形卷积的完整训练流程
  • 戴森球计划8000+工厂蓝图:从新手到大师的终极生产力指南
  • 40公斤寄什么物流便宜?40公斤寄大件物流,哪个最便宜? - 快递物流资讯
  • 如何为Windows 11 LTSC系统恢复微软商店:完整安装指南
  • Agent 记忆压缩:如何降低向量库成本
  • AI智能体安全深度实战:微软7种原生故障模式全解析 供应链攻击/目标劫持/MCP滥用攻防原理与企业级防御SOP落地
  • Product Hunt 每日热榜 | 2026-06-14
  • 2026年6月最新版南通正规房屋漏水防水补漏维修口碑名单:创维修缮机构等5家深度测评 - 一修哥咨询
  • Agent 能力评估 CheckList:你的智能体准备好上线了吗?