HarmonyOS NEXT:实现电影列表功能展示界面

时至今日HarmonyOS NEXT早已发布运行了,等其正式推出并大规模商用后,HarmonyOS的历史使命就完成并将退出历史舞台,为用户提供丰富的应用选择。但是Harmony NEXT是在HarmonyOS基础上剔除安卓(AOSP)后的产品,属于全新的手机系统。

今天实现一个简单的小案例,从零开始讲解如何通过鸿蒙开发实现一个电影列表功能的案例。

目录

新建初始项目

菜单与电影页

数据接口封装

加载与适配页

电影列表界面


新建初始项目

进入到编辑器中点击左上角的文件点击新建项目,然后选择空的 Empty Ability 进行创建:

然后接下来输入自己的项目名称就行,点击finish即可:

运行本地预览器,可以看到我们的初始项目已经跑通:

菜单与电影页

接下来开始编写我们类似H5端的tabBar导航菜单按钮的功能,这里我们可以借助官网给我们提供的选项卡(Tabs)进行类似的操作,如下所示:

接下来我们开始使用这个tabs选项卡的功能,首选我们先在pages目录下新建两个ArkTS文件然后把这两个文件都暴露出去,如下所示:

然后我们在index.ets文件下通过模块导入的方式,将两个文件进行一个导入,代码如下:

import Home from './home'
import Cinema from './cinema'@Entry
@Component
struct Index {build() {Tabs({ barPosition: BarPosition.End }) {TabContent() {Home().height('100%')}.tabBar("电影")TabContent() {Cinema().height('100%')}.tabBar("影院")}}
}

效果如下所示:

接下来我们就可以在首页组件中撰写相应的首页内容,这里我们也是借助了官方文档中的轮播器进行实现轮播图的操作,具体的代码如下所示:

@Component
struct Home {@State flag: boolean = trueimgList: string[] = ["http://124.223.69.156:5500/h5-01.jpg","http://124.223.69.156:5500/h5-02.jpg","http://124.223.69.156:5500/h5-03.png",]build() {Scroll() {Column() {// 轮播图Swiper() {ForEach(this.imgList, (item: string) => {Image(item).width('100%').height(180)})}.autoPlay(true) // 自动轮播.loop(true) // 无缝衔接// 即将上映Flex({ justifyContent: FlexAlign.SpaceAround }) {Text('正在热映').padding(10).border({ width: { bottom: this.flag ? 3 : 0 } }).borderColor(Color.Red).onClick(() => this.flag = true)Text('即将上映').padding(10).border({ width: { bottom: !this.flag ? 3 : 0 } }).borderColor(Color.Red).onClick(() => this.flag = false)}.margin({ top: 10, bottom: 10 })if (this.flag) {Text('正在热映')} else {Text('即将上映')}}}}
}
export default Home

最终呈现的效果如下所示:

上面我们仅仅是实现了静态页面的内容,如果想实现动态渲染的话就需要调用相应的接口函数,这里我们可以借助官方给我们提供的第三方仓库,网站:地址 如下所示:

然后我们下载我们调用接口的第三方库,终端执行如下命令进行安装:

ohpm install @ohos/axios

然后我们可以在项目的该文件下可以查看项目中安装的相关依赖信息:

数据接口封装

接下来开始对我们调用第三方接口进行一个初始的axios数据封装,在ets目录下新建utils工具目录,然后在工具目录当中封装如下的数据:

import axios, { AxiosResponse } from "@ohos/axios"// 参数统一处理
interface options_type {url: string,method?: string,data?: object,params?: object,headers?: object
}
// 请求返回类型
interface request_dataType {status: number,msg?: string,data: object
}// 创建axios实例
const request = axios.create({baseURL: "https://m.maizuo.com/",headers: {'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.0.4","e":"1596502176387264316178433","bc":"310100"}'}
})
const http = (options: options_type) => {const method = options.method || 'GET'if (method.toLowerCase() === 'get') {options.params = options.data}return request(options)
}
// 针对请求返回的结果处理
const resultFn = async<T> (options: options_type): Promise<T> => {const result: AxiosResponse<request_dataType> = await http(options)return result.data as T
}export default resultFn

然后接下来我们继续在ets目录下新建api目录,用于存放后期的api文件,这里我们新建home.ets文件,然后在该文件中编写对应的home页的内容数据:

import request from '../utils/request'interface return_Home_type {files: filems[],total: number
}
interface filems {poster?: string,name?: string,filmId: number,nation: string,runtime: number,actors: [name: string]
}
interface myHeader {"X-Host": string
}// 获取首页数据
export const getHomeData = (page: number) => {return request<return_Home_type>({url: `gateway?cityId=310100&pageNum=${page}&pageSize=15&type=1&k=266615`,headers: {"X-Host": "mall.film-ticket.film.list"} as myHeader,method: "GET"})
}

然后我们在首页中通过调用生命周期函数 aboutToAppear ,在页面加载之前调用函数打印数据:

然后我们调用写好的接口函数获取对应的数据:

aboutToAppear(): void {getHomeData(this.page).then(res => {console.log(JSON.stringify(res))this.moveData.films = res.films?.map((item: filems) => {item.poster = item.poster?.replace("pic.maizuo.com", "static.maizuo.com/pc/v5")return item})})
}

通过props的方式,将获取到的接口数据传递给子组件:

import { return_Home_type, filems, actors_type } from '../api/home'@Component
struct MoveList {@Prop moveData: return_Home_type@Link page: number// 处理参演人员数据fillter_actors(arr: actors_type[] | undefined) {if (!arr) return "暂无主演"return arr.map((item: actors_type) => {return item.name}).join(' ') // 通过数组转为字符串,用空格拼接}build() {Column() { // 兼容不同的终端GridRow({ gutter: { y: 20 } }) {ForEach(this.moveData.films, (item: filems) => {GridCol({span: { sm:12, md:6, lg: 3 }}) {Flex({ justifyContent: FlexAlign.SpaceBetween }) {Image(item.poster).width('20%').height(100).margin({ right: 10 })Column() {Text(item.name).fontSize(20).fontWeight(FontWeight.Bold).lineHeight(30)Text(this.fillter_actors(item.actors))Row() {Text(item.nation + '|').fontSize(15)Text(`${item.runtime}`).fontSize(15)}}.alignItems(HorizontalAlign.Start).width('80%')}.padding(10)}})}}}
}export default MoveList

最终呈现的效果如下所示:

加载与适配页

为了实现性能上的优化,这里我们需要实现一下下拉加载更多的功能,在Scroll容器当中是有下拉触底的函数的,这里我们简单的调用一下:

为了方便调用,这里我们将之前获取数据的函数抽离一下:

// 请求电影列表数据
getMovieData() {getHomeData(this.page).then(res => {this.moveData.films = res.films?.map((item: filems) => {item.poster = item.poster?.replace("pic.maizuo.com", "static.maizuo.com/pc/v5")return item})// 如果是第一页则直接覆盖move_dataif (this.page === 1) {this.moveData = res} else {// 如果是其他页则直接对films进行拼接(this.moveData as return_Home_type).films =(this.moveData as return_Home_type).films?.concat(res.films as filems[])}})
}
aboutToAppear(): void {this.getMovieData()
}

最终呈现的效果如下所示:

接下来我们给其加上一个回到顶部的按钮,这里我们首先需要给滚动容器创建实例:

然后设置停止滚动触发的函数,然后根据条件的判断来动态显示按钮:

在列表界面,调用屏幕适配变化的函数,来动态的调用获取数据的函数:

呈现的效果如下所示:

电影列表界面

接下来开始实现影院列表界面,首先我们先编写相应的接口函数,代码如下所示:

import request from '../utils/request'interface MyHeader {"X-Host": string
}
interface return_cinema_type {cinemas: cinemas[]
}
export interface cinemas {name: string,address: string
}
interface return_city_type {cities: cities[]
}
export  interface cities {name: string,cityId: number
}
// 获取影院列表
export const getCinemaData = (cityId: number) => {return request<return_cinema_type>({url: `gateway?cityId=${cityId}&ticketFlag=1&k=2500238`,headers: {"X-Host": "mall.film-ticket.cinema.list"} as MyHeader,method: "get"})
}
// 获取城市列表
export const getCity = () => {return request<return_city_type>({url: `gateway?k=2323064`,headers: {"X-Host": "mall.film-ticket.cinema.list"} as MyHeader,method: "get"})
}

接下来我们开始编写对应的影院列表内容数据的布局:

@Component
struct Cinema {@State cityName: string = '上海' // 城市名称@State cityId: number = 310100@State cinemas: cinemas[] = [] // 影院列表cityDialog: CustomDialogController = new CustomDialogController({builder: CityDialog({updateCity: (city: cities) => { this.updateCity(city) }})})updateCity(city: cities) {// 关闭弹框this.cityDialog.close()// 调用列表接口this.getData(city.cityId)// 修改显示名称this.cityName = city.name}// 请求数据getData(cityId: number) {getCinemaData(cityId).then(res=>{this.cinemas = res.cinemas})}aboutToAppear(): void {this.getData(this.cityId)}build() {Scroll() {Column() {Text(this.cityName).width('100%').margin({ bottom: 10 }).textAlign(TextAlign.Center).onClick(()=>{// 展示弹框this.cityDialog.open()})ForEach(this.cinemas, (item: cinemas) => {Text(item.name).fontSize(18).margin({ left: 5 })Text(item.address).fontSize(15).fontColor(Color.Gray).margin({ left: 5 })})}.alignItems(HorizontalAlign.Start)}}
}
export default Cinema

这里我们用到了一个弹框的效果,代码如下所示:

// 创建城市弹框
@CustomDialog
@Component
struct CityDialog {@State cities: cities[] = []controller: CustomDialogController// 定义父组件传入的通信函数updateCity: (city: cities) => void = () => {}aboutToAppear(): void {getCity().then(res => {this.cities = res.cities})}build() {Scroll() {Text('请选择城市').fontSize(20).fontColor(Color.Red).margin(5).padding(5).border({ width: { bottom: 1 } })ForEach(this.cities, (item: cities) => {Text(item.name).width('100%').height(50).textAlign(TextAlign.Center).onClick(() => {this.updateCity(item)})})}}
}

最终呈现的效果如下所示:

具体的界面搭建与接口调用参考的是 卖座电影 的一个H5案例,如下所示:

截止现在,一个简易的电影列表展示内容已经做完了,大家可以自行去练习一下!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/55164.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动驾驶系列—自动驾驶MCU架构全方位解析:从单核到多核的选型指南与应用实例

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

工作笔记【四】

对于这种&#xff0c;样式一样&#xff0c;但是图片和字体颜色不一样&#xff0c;动态渲染。 代码&#xff1a; <template><view class"page"><view class"rows" v-for"item in data"><view class"v0"><v…

基于解压缩模块的JPEG同步重压缩检测论文学习

一、论文基本信息&#xff1a; 论文题目&#xff1a;基于解压缩模块的JPEG同步重压缩检测 作者&#xff1a;王金伟1 &#xff0c;胡冰涛1 &#xff0c;张家伟1 &#xff0c;马 宾2 &#xff0c;罗向阳3 &#xff08;1.南京信息工程大学计算机学院、网络空间安全学院&#xf…

Footprint Growthly Quest 工具:赋能 Telegram 社区实现 Web3 飞速增长

作者&#xff1a;Stella L (stellafootprint.network) 在 Web3 的快节奏世界里&#xff0c;社区互动是关键。而众多 Web3 社区之所以能够蓬勃发展&#xff0c;很大程度上得益于 Telegram 平台。正因如此&#xff0c;Footprint Analytics 精心打造了 Growthly —— 一款专为 Tel…

阿里大模型算法岗面试,上来就手撕代码啊

最近已有不少大厂都在秋招宣讲了&#xff0c;也有一些在 Offer 发放阶段。 节前&#xff0c;我们邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对新手如何入门算法岗、该如何准备面试攻略、面试常考点、大模型技术趋势、算法项目落地经验分享等热门话题进行了…

怎样才能写出好的知识竞赛活动策划方案

好的知识竞赛活动策划方案是抄不会的&#xff0c;尤其是抄一堆烂方案的话&#xff0c;只会让你走偏。首要的是建立策划底层思维&#xff0c;搞清楚如何从策划角度思考问题和解决问题。注意读、思、学&#xff0c;读&#xff1a;大量读策划案例和营销案例&#xff0c;分析总结和…

当贝播放器 1.5.0 畅享原画,支持阿里网盘、杜比视界和8K播放

当贝播放器TV是一款专为智能电视设计的视频播放器&#xff0c;具有强大的解码能力&#xff0c;支持阿里网盘、百度网盘等网盘资源导入。此外&#xff0c;还支持外部设备导入&#xff0c;并能自动匹配电影海报封面、内容介绍和剧照。 大小&#xff1a;47.3M 百度网盘&#xff1…

【ARM】MDK-当选择AC5时每次点击build都会全编译

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 解决MDK中选择AC5时每次点击build都会全编译 2、 问题场景 在MDK中点击build时&#xff0c;正常会只进行增量编译&#xff0c;但目前每次点击的时候都会全编译。 3、软硬件环境 1 软件版本&#xff1a;Keil MDK 5.…

html+css+js实现dialog对话框

实现效果 HTML部分 <span class"text">点击打开 Dialog</span><!-- 警告框 --><div class"alert"><div class"header"><i>X</i> </div><div class"content">确认关闭</di…

基于php的律所管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

从0开始深度学习(6)——Pytorch动态图机制(前向传播、反向传播)

PyTorch 的动态计算图机制是其核心特性之一&#xff0c;它使得深度学习模型的开发更加灵活和高效。 0 计算图 计算图&#xff08;Computation Graph&#xff09;是一种用于表示数学表达式或程序流程的图形结构&#xff0c;可以将复杂的表达式分解成一系列简单的操作&#xff0…

详解代理模式-【静态代理与JDK动态代理】(非常的斯国一)

目录 静态代理 什么是静态代理: ​ 特点: 例子&#xff1a; JDK动态代理&#xff08;主要讲点&#xff09; 大纲&#xff1a; 1、与静态代码的联系 2、JDK动态代理的主流程 3、Proxy的源码 整体概述&#xff1a; 重要点的翻译 &#xff1a; newProxyInstance源码&am…

深信服2025届全球校招研发笔试-C卷(AK)

前面14个填空题 T1 已知 子数组 定义为原数组中的一个连续子序列。现给定一个正整数数组 arr&#xff0c;请计算该数组内所有可能的奇数长度子数组的数值之和。 输入描述 输入一个正整数数组arr 输出描述 所有可能的奇数长度子数组的和 示例 1 输入 1,4,2,5,3 输出 58 说明 …

使用 Light Chaser 进行大屏数据可视化

引言 在当今数据驱动的世界中&#xff0c;数据可视化变得越来越重要。Light Chaser 是一款基于 React 技术栈的大屏数据可视化设计工具&#xff0c;通过简单的拖拽操作&#xff0c;你可以快速生成漂亮、美观的数据可视化大屏和看板。本文将介绍如何使用 Light Chaser 进行数据…

828华为云征文|部署在线文档应用程序 CodeX Docs

828华为云征文&#xff5c;部署在线文档应用程序 CodeX Docs 一、Flexus云服务器X实例介绍二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置2.4 Docker 环境搭建 三、Flexus云服务器X实例部署 CodeX Docs3.1 CodeX Docs 介绍3.2 CodeX Docs 部署3.3 CodeX…

RabbitMQ应用

RabbitMQ 共提供了7种⼯作模式, 进⾏消息传递 一、七种模式的概述 1、Simple(简单模式) P:生产者,就是发送消息的程序 C:消费者,就是接收消息的程序 Queue:消息队列,类似⼀个邮箱, 可以缓存消息; ⽣产者向其中投递消息, 消费者从其中取出消息 特点: ⼀个⽣产者P,⼀…

小米2025届软件开发工程师(C/C++/Java)(编程题AK)

选择题好像也是25来个 编程题 T1 题目描述 小明喜欢解决各种数学难题。一天&#xff0c;他遇到了一道有趣的题目:他需要帮助他的朋友们完成一个排序任务。小明得到两个长度为 n 的数组a[]和b[]。他可以在两个数组对应位置进行交换&#xff0c;即选定一个位置 i &#xff0c…

《pyqt+open3d》open3d可视化界面集成到qt中

《pyqtopen3d》open3d可视化界面集成到qt中 一、效果显示二、代码三、资源下载 一、效果显示 二、代码 参考链接 main.py import sys import open3d as o3d from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget from PyQt5.QtGui import QWindow from PyQt5.Qt…

App模拟下载场景的demo

摘要 目的&#xff1a;提供一个稳定的下载场景&#xff0c;可以手动触发和定时触发下载&#xff0c;每次下载相同大小文件&#xff0c;研究下载场景的功耗影响 原理&#xff1a;把电脑当做服务器&#xff0c;手机测试App固定下载电脑存放的某个XXXMB的大文件&#xff0c;基于…

C语言进阶版第14课—内存函数

文章目录 1. memcpy函数的使用和模拟实现1.1 memcpy函数的使用1.2 模拟实现memcpy函数 2. memmove函数的使用和模拟实现2.1 memmove函数的使用2.2 memmove函数的模拟实现 3. memset函数4. memcmp函数 1. memcpy函数的使用和模拟实现 1.1 memcpy函数的使用 memcpy函数的原形voi…