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

HarmonyOS NEXT应用开发边学边玩系列:从零实现一影视APP (五、电影详情页的设计实现)

在上一篇文章中,完成了电影列表页的开发。接下来,将进入电影详情页的设计实现阶段。这个页面将展示电影的详细信息,包括电影海报、评分、简介以及相关影人等。将使用 HarmonyOS 提供的常用组件,并结合第三方库 nutpi/axios 来实现网络请求。下面,一步步地来看如何实现电影详情页。

在这里插入图片描述
开源项目地址:https://atomgit.com/csdn-qq8864/hmmovie

好的作品是需要不断打磨,在你的学习和体验过程中有任何问题,欢迎到我的开源项目代码仓下面提交issue,持续优化。

获取电影详情接口

首先,需要定义一个用于获取电影详情的接口。这里使用 axiosClient.post 方法来实现,代码如下:

export const getDetailMv = (id: string): HttpPromise<DetailMvResp> => axiosClient.post({ url: '/detailmovie', data: { id: id } });

电影详情接口的具体信息如下:

POST http://120.27.146.247:8000/api/v1/detailmovie
Content-Type: application/json{"id": "1292052"
}
电影详情页的组件使用

在电影详情页中,将使用 BadgeSymbolSpanButtonRating 等组件来展示电影的详细信息。

  1. Badge 组件

    Badge 组件用于在某个组件的右上角显示一个标记,通常用于展示某种数量或状态。在电影详情页中,将使用 Badge 组件来展示“想看”和“看过”的数量。

  2. SymbolSpan 组件

    SymbolSpan 组件用于在文本中嵌入图标。在电影详情页中,将使用 SymbolSpan 组件来展示“想看”和“看过”的图标。

  3. Button 组件

    Button 组件用于创建按钮,用户可以通过点击按钮来执行特定的操作。在电影详情页中,将使用 Button 组件来创建“播放”按钮,用户点击后可以跳转到视频播放页面。

  4. Rating 组件

    Rating 组件用于展示评分。在电影详情页中,将使用 Rating 组件来展示电影的豆瓣评分。

电影详情页的实现

下面,将展示电影详情页的具体实现代码:

import { getDetailMv, getMovieSrc } from "../../common/api/movie"
import { Log } from "../../utils/logutil"
import { BusinessError } from "@kit.BasicServicesKit"
import { DetailMvResp, DetailMvRespCast } from "../../common/bean/DetailMvResp"
import { LengthMetrics, promptAction } from "@kit.ArkUI"
import { MvSourceResp } from "../../common/bean/MvSourceResp"@Builder
export function MovieDetailPageBuilder() {Detail()
}@Component
struct Detail {pageStack: NavPathStack = new NavPathStack()private uid = ''@State detailData: DetailMvResp | null = null;private srcData: MvSourceResp | null = null;private description: string = ''private isToggle = false@State toggleText: string = ''@State toggleBtn: string = '展开'build() {NavDestination() {Column({ space: 0 }) {Row() {Image(this.detailData?.images).objectFit(ImageFit.Auto).width(120).borderRadius(5)Column({ space: 8 }) {Text(this.detailData?.title).fontSize(18)Text(this.detailData?.year + " " + this.detailData?.genre).fontSize(14)Row() {Badge({count: this.detailData?.wish_count,maxCount: 10000,position: BadgePosition.RightTop,style: { badgeSize: 22, badgeColor: '#fffab52a' }}) {Row() {Text() {SymbolSpan($r('sys.symbol.heart')).fontWeight(FontWeight.Lighter).fontSize(32).fontColor(['#fffab52a'])}Text('想看')}.backgroundColor('#f8f4f5').borderRadius(5).padding(5)}.padding(8)Blank(10).width(40)Badge({count: this.detailData?.reviews_count,maxCount: 10000,position: BadgePosition.RightTop,style: { badgeSize: 22, badgeColor: '#fffab52a' }}) {Row() {Text() {SymbolSpan($r('sys.symbol.star')).fontWeight(FontWeight.Lighter).fontSize(32).fontColor(['#fffab52a'])}Text('看过')}.backgroundColor('#f8f4f5').borderRadius(5).padding(5)}.padding(8)}Button('播放', { buttonStyle: ButtonStyleMode.NORMAL, role: ButtonRole.NORMAL }).borderRadius(8).borderColor('#fffab52a').fontColor('#fffab52a').width(100).height(35).onClick(() => {console.info('Button onClick')if (this.srcData != null) {this.pageStack.pushDestinationByName("VideoPlayerPage", { item: { video: this.srcData.urls[0], tvurls: this.srcData.tvurls, title: this.srcData.title, desc: this.detailData?.summary } }).catch((e: Error) => {// 跳转失败,会返回错误码及错误信息console.log(`catch exception: ${JSON.stringify(e)}`)}).then(() => {// 跳转成功});} else {promptAction.showToast({ message: '暂无资源' })}})}.alignItems(HorizontalAlign.Start) // 水平方向靠左对齐.justifyContent(FlexAlign.Start)   // 垂直方向靠上对齐.padding(10)}.height(160).width('100%')Row() {Text('豆瓣评分').fontSize(16).padding(5)Rating({ rating: (this.detailData?.rate ?? 0) / 2, indicator: true }).stars(5).stepSize(0.5).height(28)Text(this.detailData?.rate.toString()).fontColor('#fffab52a').fontWeight(FontWeight.Bold).fontSize(36).padding(5)}.width('100%').height(80).borderRadius(5).backgroundColor('#f8f4f5').margin(20)Text('简介').fontSize(18).padding({ bottom: 10 }).fontWeight(FontWeight.Bold).alignSelf(ItemAlign.Start)Text(this.toggleText).fontSize(14).lineHeight(20).alignSelf(ItemAlign.Start)Text(this.toggleBtn).fontSize(14).fontColor(Color.Gray).padding(10).alignSelf(ItemAlign.End).onClick(() => {this.isToggle = !this.isToggleif (this.isToggle) {this.toggleBtn = '收起'this.toggleText = this.description} else {this.toggleBtn = '展开'this.toggleText = this.description.substring(0, 100) + '...'}})Text('影人').fontSize(18).padding({ bottom: 10 }).fontWeight(FontWeight.Bold).alignSelf(ItemAlign.Start)Scroll() {Row({ space: 5 }) {ForEach(this.detailData?.cast, (item: DetailMvRespCast) => {Column({ space: 0 }) {Image(item.cover).objectFit(ImageFit.Auto).height(120).borderRadius(5).onClick(() => {})Text(item.name).alignSelf(ItemAlign.Center).maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis }).fontSize(14).padding(10)}.justifyContent(FlexAlign.Center)}, (itm: DetailMvRespCast, idx) => itm.id)}}.scrollable(ScrollDirection.Horizontal)}.padding({ left: 10, right: 10 })}.title("电影详情").width('100%').height('100%').onReady(ctx => {this.pageStack = ctx.pathStack//从上个页面拿参数this.pageStack.getParamByName("MovieDetailPage")interface params {id: string;}let par = ctx.pathInfo.param as paramsLog.debug("par:%s", par.id)this.uid = par.id}).onShown(() => {console.info('Detail onShown');getDetailMv(this.uid).then((res) => {Log.debug(res.data.message)Log.debug("request", "res.data.code:%{public}d", res.data.code)this.detailData = res.datathis.description = this.detailData.summarythis.toggleText = this.description.substring(0, 100) + '...'}).catch((err: BusinessError) => {Log.debug("request", "err.data.code:%d", err.code)Log.debug("request", err.message)});getMovieSrc(this.uid).then((res) => {Log.debug(res.data.message)Log.debug("request", "res.data.code:%{public}d", res.data.code)if (res.data.code == 0) {this.srcData = res.data}}).catch((err: BusinessError) => {Log.debug("request", "err.data.code:%d", err.code)Log.debug("request", err.message)});})}
}
折叠效果的实现

在电影详情页中,对于电影的简介,使用了折叠效果,即默认只显示部分简介内容,用户点击“展开”按钮后可以查看完整简介。这个效果的实现主要通过控制 Text 组件的显示内容来实现。具体代码如下:

Text(this.toggleText).fontSize(14).lineHeight(20).alignSelf(ItemAlign.Start)
Text(this.toggleBtn).fontSize(14).fontColor(Color.Gray).padding(10).alignSelf(ItemAlign.End).onClick(() => {this.isToggle = !this.isToggleif (this.isToggle) {this.toggleBtn = '收起'this.toggleText = this.description} else {this.toggleBtn = '展开'this.toggleText = this.description.substring(0, 100) + '...'}
})

通过上述代码,实现了电影简介内容的折叠效果。

总结

在本文中,完成了电影详情页的设计与实现。主要使用了 BadgeSymbolSpanButtonRating 等组件,并结合 nutpi/axios 库来实现网络请求。通过这些技术,可以快速地开发出功能丰富、用户体验良好的影视应用。希望本文对你有所帮助。

作者介绍

作者:csdn猫哥

原文链接:https://blog.csdn.net/yyz_1987

团队介绍

坚果派团队由坚果等人创建,团队拥有12个华为HDE带领热爱HarmonyOS/OpenHarmony的开发者,以及若干其他领域的三十余位万粉博主运营。专注于分享HarmonyOS/OpenHarmony、ArkUI-X、元服务、仓颉等相关内容,团队成员聚集在北京、上海、南京、深圳、广州、宁夏等地,目前已开发鸿蒙原生应用和三方库60+,欢迎交流。

版权声明

本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

其他资源

官方系统图标资源:https://developer.huawei.com/consumer/cn/doc/design-guides/system-icons-0000001929854962

https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkui/arkui-ts/ts-basic-components-symbolSpan.md

https://developer.huawei.com/consumer/cn/design/harmonyos-symbol/

相关文章:

HarmonyOS NEXT应用开发边学边玩系列:从零实现一影视APP (五、电影详情页的设计实现)

在上一篇文章中&#xff0c;完成了电影列表页的开发。接下来&#xff0c;将进入电影详情页的设计实现阶段。这个页面将展示电影的详细信息&#xff0c;包括电影海报、评分、简介以及相关影人等。将使用 HarmonyOS 提供的常用组件&#xff0c;并结合第三方库 nutpi/axios 来实现…...

hive表修改字段类型没有级连导致历史分区报错

一&#xff1a;问题背景 修改hive的分区表时有级连概念&#xff0c;指字段的最新状态&#xff0c;默认只对往后的分区数据生效&#xff0c;而之前的分区保留历史元数据状态。好处就是修改语句的效率很快&#xff0c;坏处就是如果历史分区的数据还有用&#xff0c;那就回发生分…...

云上贵州多彩宝荣获仓颉社区先锋应用奖 | 助力数字政务新突破

在信息技术应用创新的浪潮中&#xff0c;仓颉社区吸引了众多企业和开发者的积极参与&#xff0c;已有多个应用成功落地&#xff0c;展现出蓬勃的创新活力。仓颉编程语言精心遴选了在社区建设、应用创新、开源共建、技术布道等方面做出突出贡献的优秀项目应用&#xff0c;并颁发…...

JS宏进阶:JS宏中的文件系统FileSystem

FileSystem对象中包含文件和文件夹的一些基本和常见的操作接口。比如&#xff1a;判断路径是否存在、创建文件夹、创建文件、读取文件等等。他的出现可以取代文件流对txt或csv等文件的操作。官方文档网址&#xff1a;https://open.wps.cn/previous/docs/client/wpsLoad&#xf…...

XML序列化和反序列化的学习

1、基本介绍 在工作中&#xff0c;经常为了调通上游接口&#xff0c;从而对请求第三方的参数进行XML序列化&#xff0c;这里常使用的方式就是使用JAVA扩展包中的相关注解和类来实现xml的序列化和反序列化。 2、自定义工具类 import javax.xml.bind.JAXBContext; import javax.x…...

npm ERR! code CERT_HAS_EXPIRED

很不幸看到这个提示。 查了很多网上的解决方案&#xff0c;都提到一个解决方案&#xff1a; npm install -g npmlatest 靠就是执行install报的错&#xff0c;你要我通过install来解决这个问题。可见大多数人都是转发&#xff0c;从不自己试试。 第二个是看系统时间。这个基…...

30分钟内搭建一个全能轻量级springboot 3.4 + 脚手架 <5> 5分钟集成好caffeine并使用注解操作缓存

快速导航 <1> 5分钟快速创建一个springboot web项目 <2> 5分钟集成好最新版本的开源swagger ui&#xff0c;并使用ui操作调用接口 <3> 5分钟集成好druid并使用druid自带监控工具监控sql请求 <4> 5分钟集成好mybatisplus并使用mybatisplus generator自…...

【设计模式-结构型】装饰器模式

一、什么是装饰器模式 装饰器模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;它的核心思想是在不改变原有对象结构的情况下&#xff0c;动态地给对象增加一些功能&#xff0c;从而达到扩展功能的目的。举个例子&#xff0c;今天在家妈妈给蒸馒…...

分布式数据存储基础与HDFS操作实践(副本)

以下为作者本人撰写的报告&#xff0c;步骤略有繁琐&#xff0c;不建议作为参考内容&#xff0c;可以适当浏览&#xff0c;进一步理解。 一、实验目的 1、理解分布式文件系统的基本概念和工作原理。 2、掌握Hadoop分布式文件系统&#xff08;HDFS&#xff09;的基本操作。 …...

Linux 进程前篇(冯诺依曼体系结构和操作系统)

目录 一.冯诺依曼体系结构 1.概念 2.硬件层面的数据流 3.总结加补充 二.操作系统 (Operating System) 1.概念 2.设计OS的目的 3.定位 4.操作系统的管理 5.计算机体系的层状结构 在我们认识进程之前&#xff0c;我们先了解什么是冯诺依曼体系结构 一.冯诺依曼体系结构…...

Springboot Redisson 分布式锁、缓存、消息队列、布隆过滤器

redisson-spring-boot-starter 是 Redisson 提供的 Spring Boot 集成包&#xff0c;旨在简化与 Redis 的交互&#xff0c;包括分布式锁、缓存、消息队列、布隆过滤器等功能的实现。 Maven 依赖 在 Spring Boot 项目中添加 redisson-spring-boot-starter 依赖&#xff1a; <…...

【C语言】_字符串拷贝函数strcpy

目录 1. 函数声明及功能 2. 使用示例 3. 注意事项 4. 模拟实现 4.1 第一版&#xff1a;基本功能判空const修饰 4.2 第二版&#xff1a;优化对于\0的单独拷贝 4.3 第三版&#xff1a;仿strcpy的char*返回值 1. 函数声明及功能 char * strcpy ( char * destination, cons…...

基于 Vue 的拖拽缩放卡片组件:实现思路、方法及使用指南

引言 在前端开发中&#xff0c;实现可交互的组件能够极大地提升用户体验。本文将介绍一个基于 Vue 封装的可缩放卡片组件&#xff0c;从实现思路、代码具体实现以及使用方法等方面进行详细阐述&#xff0c;帮助开发者更好地理解和运用这一组件。项目源码地址&#xff1a;https…...

nginx 实现 正向代理、反向代理 、SSL(证书配置)、负载均衡 、虚拟域名 ,使用其他中间件监控

我们可以详细地配置 Nginx 来实现正向代理、反向代理、SSL、负载均衡和虚拟域名。同时&#xff0c;我会介绍如何使用一些中间件来监控 Nginx 的状态和性能。 1. 安装 Nginx 如果你还没有安装 Nginx&#xff0c;可以通过以下命令进行安装&#xff08;以 Ubuntu 为例&#xff0…...

Kafka客户端-“远程主机强迫关闭了一个现有的连接”故障排查及解决

Kafka客户端-“远程主机强迫关闭了一个现有的连接”故障排查及解决 1. 故障现象 Kafka客户端发送数据时&#xff0c;出现“远程主机强迫关闭了一个现有的连接”错误&#xff0c;导致数据发送失败。错误信息如下&#xff1a; 2. 故障排查 【1】. 查看服务网络状态 出现故障…...

Node.js - Express框架

1. 介绍 Express 是一个基于 Node.js 的 Web 应用程序框架&#xff0c;主要用于快速、简便地构建 Web 应用程序 和 API。它是目前最流行的 Node.js Web 框架之一&#xff0c;具有轻量级、灵活和功能丰富的特点。 核心概念包括路由&#xff0c;中间件&#xff0c;请求与响应&a…...

AWS Lambda

AWS Lambda 是 Amazon Web Services&#xff08;AWS&#xff09;提供的无服务器计算服务&#xff0c;它让开发者能够运行代码而不需要管理服务器或基础设施。AWS Lambda 会自动处理代码的执行、扩展和计费&#xff0c;开发者只需关注编写和部署代码&#xff0c;而无需担心底层硬…...

mysql 如何快速删除表数据

在数据库管理中, 经常会遇到需要删除大量数据的情况. 对于 MySQL 数据库而言, 如何高效快速地删除数据是一个值得深入探讨的问题. 本文将详细介绍几种在 MySQL 中快速删除数据的方法及相关注意事项. delete 语句 delete 语句可以删除符合条件的指定数据, 但是在删除大量数据…...

物联网网关Web服务器--lighttpd服务器部署与应用测试

以下是在国产ARM处理器E2000飞腾派开发板上部署 lighttpd 并进行 CGI 应用开发的步骤&#xff1a; 1、lighttpd简介 Lighttpd 是一款轻量级的开源 Web 服务器软件&#xff0c;具有以下特点和功能&#xff1a; 特点 轻量级&#xff1a;Lighttpd 在设计上注重轻量级和高效性&a…...

vmware虚拟机配置ubuntu 18.04(20.04)静态IP地址

VMware版本 &#xff1a;VMware Workstation 17 Pro ubuntu版本&#xff1a;ubuntu-18.04.4-desktop-amd64 主机环境 win11 1. 修改 VMware虚拟网络编辑器 打开vmware&#xff0c;点击顶部的“编辑"菜单&#xff0c;打开 ”虚拟化网络编辑器“ 。 选择更改设置&#…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

基于Java+VUE+MariaDB实现(Web)仿小米商城

仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意&#xff1a;运行前…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成&#xff0c;具体方法取决于设备类型&#xff08;如USB麦克风、3.5mm接口麦克风或HDMI音频输入&#xff09;。以下是详细指南&#xff1a; 1. 连接音频输入设备 USB麦克风/声卡&#xff1a;直接插入树莓派的USB接口。3.5mm麦克…...

离线语音识别方案分析

随着人工智能技术的不断发展&#xff0c;语音识别技术也得到了广泛的应用&#xff0c;从智能家居到车载系统&#xff0c;语音识别正在改变我们与设备的交互方式。尤其是离线语音识别&#xff0c;由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力&#xff0c;广…...

Matlab实现任意伪彩色图像可视化显示

Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中&#xff0c;如何展示好看的实验结果图像非常重要&#xff01;&#xff01;&#xff01; 1、灰度原始图像 灰度图像每个像素点只有一个数值&#xff0c;代表该点的​​亮度&#xff08;或…...

Vue3中的computer和watch

computed的写法 在页面中 <div>{{ calcNumber }}</div>script中 写法1 常用 import { computed, ref } from vue; let price ref(100);const priceAdd () > { //函数方法 price 1price.value ; }//计算属性 let calcNumber computed(() > {return ${p…...