当前位置: 首页 > 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.rkmt.cn/news/1525833.html

相关文章:

  • 2026年6月市场比较好的真空计公司推荐,真空泵/真空计/氦质谱检漏仪,真空计销售商哪家好 - 品牌推荐师
  • 深入解析PowerPC SPR:从编码机制到缓存与性能监控实战
  • 零代码构建AI工作流:Awesome-Dify-Workflow让每个人都能成为AI应用开发者
  • 高效获取B站高质量视频:downkyi哔哩下载姬专业应用指南
  • MPC8280内存控制器与L2缓存接口设计详解
  • AI智能体安全深度实战:微软7种原生故障模式全解析 供应链攻击/目标劫持/MCP滥用攻防原理与企业级防御SOP落地
  • 从DCNv1到v3:手把手带你用MMDetection/YOLO跑通可变形卷积的完整训练流程
  • 2026年6月最新版南通正规房屋漏水防水补漏维修口碑名单:创维修缮机构等5家深度测评 - 一修哥咨询
  • 微信小程序逆向工程核心技术解析:深入理解wxappUnpacker的架构突破与安全价值
  • 2026年6月最新版六盘水正规房屋漏水防水补漏维修口碑名单:创维修缮机构等5家深度测评 - 一修哥咨询
  • wxapkg-convertor深度解析:微信小程序反编译技术终极指南
  • 11-GIL不是性能杀手(上)-CPU密集vsIO密集的实测对比
  • CVE-2026-5027全链路攻防深度剖析:Langflow未认证远程代码执行漏洞原理、在野利用与AI低代码安全体系建设
  • 3分钟解决TranslucentTB的Microsoft.VCLibs.140.00缺失错误:完整配置指南
  • 从淘汰到重生:一个开源项目如何让150+款老Mac焕发新生
  • 网页时光机:3个技巧让你永远告别404错误,轻松找回消失的网页内容
  • PC端微信QQ防撤回补丁:完整保留聊天记录的技术方案
  • 《Python程序设计》实验4报告
  • 破局进口垄断,深耕本土市场|膜利法则以全产业链实力,重塑国产汽车膜新格局 - 资讯速览
  • UniApp消息推送选型实战:UniPush 2.0 vs 极光推送,从成本到送达率的深度对比
  • 3个步骤掌握Maid:在手机上免费运行AI大模型的终极指南
  • 终极方案:3步彻底解决Cursor自动更新导致试用重置问题
  • 广州擅长职务侵占罪刑事律师推荐榜(2026):涉企经济犯罪辩护深度解析 - 互联网科技品牌测评
  • 基于ML307R Cat.1 4G模块的ESP32智能硬件双网络架构设计与实现
  • 2026年6月最新版来宾正规房屋漏水防水补漏维修口碑名单:创维修缮机构等5家深度测评 - 一修哥咨询
  • OpenGL基础
  • 5分钟掌握猫抓Cat-Catch:浏览器资源嗅探工具的完整使用指南
  • MPC8245 DUART深度解析:从异步串口原理到寄存器编程实战
  • 鸿蒙原生应用实战(五)ArkUI 图片拼接/长图生成:多图合并 + Canvas 绘制 + 导出分享
  • 终极BT下载加速指南:如何用trackerslist项目彻底告别龟速下载