鸿蒙原生应用开发实战(四):电影详情与评分评价 — 电影清单App

鸿蒙原生应用开发实战(四):电影详情与评分评价 — 电影清单App 鸿蒙原生应用开发实战四电影详情与评分评价 — 电影清单App前言前三篇文章我们完成了首页、添加电影和列表页面。当用户点击某部电影时需要进入详情页面查看完整信息、打分和写影评。这篇文章将开发电影详情页这是最富交互性的页面。本文涵盖路由传参接收电影ID电影信息展示布局五角星评分组件状态切换与收藏影评编辑TextArea数据更新与删除一、详情页面设计┌──────────────────────────────────┐ │ 返回 电影详情 │ ├──────────────────────────────────┤ │ │ │ 星际穿越 │ │ 2014 · 科幻 │ │ 导演: 克里斯托弗·诺兰 │ ├──────────────────────────────────┤ │ [ 想看] [▶️ 在看] [✅ 已看] │ ← 状态切换 ├──────────────────────────────────┤ │ ⭐ 已收藏 [] │ ← 收藏开关 ├──────────────────────────────────┤ │ 我的评分 │ │ ★★★★★ │ ← 星级显示 │ ★ ☆ ☆ ☆ ☆ │ ← 点击评分 ├──────────────────────────────────┤ │ 我的影评 编辑 │ ← 展开编辑 │ 时间、空间与爱的史诗。 │ ├──────────────────────────────────┤ │ 添加日期: 2025-01-12 │ │ │ │ [ 删除这部电影 ] │ └──────────────────────────────────┘二、路由传参2.1 跳转传参从列表页或首页跳转到详情页时传递电影IDrouter.pushUrl({url:pages/DetailPage,params:{movieId:item.id}});2.2 接收参数在详情页的aboutToAppear中接收参数aboutToAppear():void{letparamsrouter.getParams()asRecordstring,Object;letmovieIdparams[movieId]asstring;letstoredAppStorage.getMovie[](movies);if(stored){this.moviesstored;for(leti0;istored.length;i){if(stored[i].idmovieId){this.moviestored[i];this.editReviewstored[i].review;break;}}}}2.3 状态定义EntryComponentstruct DetailPage{Statemovie:Movie{id:,title:,year:0,director:,rating:0,status:MovieStatus.WANT_TO_WATCH,isFavorite:false,review:,dateAdded:,genreId:};Statemovies:Movie[][];StateeditReview:string;StateshowReviewInput:booleanfalse;}三、电影信息展示3.1 标题区域Column(){Text(getGenreById(this.movie.genreId)?.icon??).fontSize(56).margin({bottom:8})Text(this.movie.title).fontSize(24).fontWeight(FontWeight.Bold).fontColor(#333333).textAlign(TextAlign.Center)Text(this.movie.year · (getGenreById(this.movie.genreId)?.name??未知)).fontSize(14).fontColor(#999999).margin({top:4})Text(导演: (this.movie.director?this.movie.director:未知)).fontSize(14).fontColor(#999999).margin({top:2})}.width(100%).padding(20).backgroundColor(#FFFFFF).alignItems(HorizontalAlign.Center)3.2 状态切换BuilderstatusBtn(label:string,status:MovieStatus){Text(label).fontSize(13).fontColor(this.movie.statusstatus?#FFFFFF:#666666).backgroundColor(this.movie.statusstatus?#6C63FF:#F0F0F0).padding({left:12,right:12,top:6,bottom:6}).borderRadius(14).margin({right:6}).onClick((){this.changeStatus(status);})}四、收藏功能4.1 Toggle 开关使用 HarmonyOS 的 Toggle 组件实现收藏开关Row(){Text(this.movie.isFavorite?⭐ 已收藏: 收藏).fontSize(16).fontColor(this.movie.isFavorite?#FFA502:#999999)Blank()Toggle({type:ToggleType.Checkbox,isOn:this.movie.isFavorite}).onChange((v:boolean){this.movie.isFavoritev;this.saveMovieData();})}.width(94%).padding(14).backgroundColor(#FFFFFF).borderRadius(12).margin({top:10})4.2 数据持久化每次状态变化立即保存到 AppStoragesaveMovieData():void{letupdatedfalse;for(leti0;ithis.movies.length;i){if(this.movies[i].idthis.movie.id){this.movies[i]this.movie;updatedtrue;break;}}if(!updated){this.movies.push(this.movie);}AppStorage.setMovie[](movies,this.movies);}五、星级评分组件5.1 星级显示使用 unicode 字符 ★☆ 显示评分exportfunctionstarsString(rating:number):string{letfull★.repeat(rating);letempty☆.repeat(5-rating);returnfullempty;}5.2 可点击评分Text(我的评分).fontSize(14).fontColor(#999999).width(100%)// ★★★★★ 显示当前评分Row(){Text(starsString(this.movie.rating)).fontSize(32).fontColor(#FFA502).letterSpacing(4)}.width(100%).margin({top:6})// 可点击的星星Row(){this.starBtn(1)this.starBtn(2)this.starBtn(3)this.starBtn(4)this.starBtn(5)}.width(100%).margin({top:6})5.3 星星按钮BuilderstarBtn(rating:number){Text(ratingthis.movie.rating?★:☆).fontSize(30).fontColor(#FFA502).margin({right:4}).onClick((){this.setRating(rating);})}点击时更新评分并保存setRating(r:number):void{this.movie.ratingr;this.saveMovieData();}六、影评编辑6.1 文本编辑区点击「编辑」按钮展开 TextArea 输入区Column(){Row(){Text(我的影评).fontSize(14).fontColor(#999999)Blank()Text(编辑).fontSize(13).fontColor(#6C63FF).onClick((){this.editReviewthis.movie.review;this.showReviewInput!this.showReviewInput;})}.width(100%)if(this.showReviewInput){TextArea({placeholder:写下你的影评...,text:this.editReview}).fontSize(15).height(100).width(100%).placeholderColor(#CCCCCC).backgroundColor(#F9F9F9).margin({top:8}).onChange((v:string){this.editReviewv;})Button(保存影评).width(100%).height(36).backgroundColor(#6C63FF).borderRadius(18).fontSize(14).fontColor(#FFFFFF).margin({top:6}).onClick((){this.saveReview();})}else{Text(this.movie.review?this.movie.review:暂无影评点击编辑添加...).fontSize(15).fontColor(this.movie.review?#333333:#CCCCCC).width(100%).margin({top:6})}}6.2 保存影评saveReview():void{this.movie.reviewthis.editReview;this.showReviewInputfalse;this.saveMovieData();}七、删除功能7.1 删除按钮Button(删除这部电影).width(94%).height(44).backgroundColor(#FFFFFF).fontColor(#FF4757).fontSize(16).borderRadius(22).border({width:1,color:#FF4757}).margin({top:16,bottom:30}).onClick((){this.deleteMovie();})7.2 删除逻辑deleteMovie():void{letnewList:Movie[][];for(leti0;ithis.movies.length;i){if(this.movies[i].id!this.movie.id){newList.push(this.movies[i]);}}AppStorage.setMovie[](movies,newList);router.back();}八、完整交互流程用户点击电影卡片 → ListPage pushUrl 传递 movieId → DetailPage aboutToAppear 读取参数 → 从 AppStorage 查找对应电影 → 展示完整信息 用户修改评分/状态/收藏 → 立即更新 State movie → 调用 saveMovieData() 保存到 AppStorage → 数据实时持久化 用户编辑影评 → 点击「编辑」展开 TextArea → 输入内容后点击「保存影评」 → 数据保存并收起编辑区 用户删除电影 → 点击「删除这部电影」 → 从列表中移除 → 更新 AppStorage → 返回列表页九、ArkTS 注意事项9.1 对象初始化由于 ArkTS 严格模式要求对象字面量有显式类型初始化State movie时需要完整赋值Statemovie:Movie{id:,title:,year:0,director:,rating:0,status:MovieStatus.WANT_TO_WATCH,isFavorite:false,review:,dateAdded:,genreId:};9.2 路由参数类型转换router.getParams()返回的类型需要用as Recordstring, Object断言再取值letparamsrouter.getParams()asRecordstring,Object;letmovieIdparams[movieId]asstring;总结本文完成了电影详情页面的开发✅ 路由传参与数据加载✅ 状态切换想看/在看/已看✅ 收藏功能Toggle 实时保存✅ 星级评分组件点击评分✅ 影评编辑TextArea 展开/收起✅ 删除功能至此应用的 CRUD增删改查已经全部实现下一篇将开发个人中心页面完成数据统计和分类分析系列目录✅ 第一篇项目搭建与首页概览✅ 第二篇添加电影与表单交互✅ 第三篇电影列表与搜索筛选✅ 第四篇电影详情与评分评价本篇 第五篇个人中心与数据统计