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.xdnf.cn/news/1552554.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

C++进阶(3): 二叉搜索树

二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一颗空树&#xff0c;或者具有以下性质的二叉树&#xff1a; 若它的左子树不为空&#xff0c;则左子树上所有的节点的值都小于等于 根节点的值若它的右子树不为空&#xff0c;则右子树上所有的节点的值都大于等…

嘉立创编辑器中删除自己画的封装

快速创建一个元件及封装可参考 需要删除封装的原因 在添加新的元件时&#xff0c;有时候明明关联了封装和符号&#xff0c;但在原理图中添加元件时会出现封装未添加的问题。可能是这个立创EDA中有些功能问题很少使用&#xff0c;所以没完善。而且发现在封装中可以关联器件&am…

【开源鸿蒙】OpenHarmony 5.0.0 发布了,速来下载最新代码

【开源鸿蒙】OpenHarmony 5.0.0 发布了&#xff0c;速来下载最新代码 一、写在前面二、准备命令工具三、配置用户信息四、下载OpenHarmony源码4.1 使用ssh协议下载&#xff08;推荐&#xff09;4.2 使用https协议下载 五、下载编译工具链六、参考链接 今天是9月30号&#xff0c…

ThreadLocal原理解析及面试

基本使用 讲原理之前&#xff0c;我简单写个demo小程序 public class TestThreadLocal {public static void main(String[] args) throws InterruptedException {ThreadLocal<String> tl new ThreadLocal();/**主线程设置了一个值*/tl.set("SSSSSs");//tl.…

阿里云域名注册购买和备案

文章目录 1、阿里云首页搜索 域名注册2、点击 控制台3、域名控制台 1、阿里云首页搜索 域名注册 2、点击 控制台 3、域名控制台

linux如何与网络时间对齐(雪花算法ID重复)

文章目录 前言一、可能引发什么问题&#xff1f;二、调整步骤1.查看当前系统时间2.修改为中国时区3.同步网络时间4. 雪花id重复 总结 前言 linux服务器是部署服务的不二之选,有个小问题不可忽略&#xff1a; 会发现默认的服务器时间并非中国时区,时间也是相差八小时,中国时区…

8640 希尔(shell)排序

### 思路 希尔排序是一种基于插入排序的排序算法&#xff0c;通过将待排序数组分割成多个子序列分别进行插入排序来提高效率。初始增量d为n/2&#xff0c;之后每次减半&#xff0c;直到d为1。 ### 伪代码 1. 读取输入的待排序关键字个数n。 2. 读取n个待排序关键字并存储在数组…

Git傻傻分不清楚(上)

环境&#xff1a;Idea2022.3.3、Git&#xff08;忘辽~&#xff09; 怎么上传自己的项目到Github上&#xff1f; Idea和Github进行账号关联将项目上传到本地仓库&#xff08;Commit&#xff09;将本地仓库中的项目上传到Github上&#xff08;Push&#xff09; 一、关联账号 …

【Java SE 题库】移除元素(暴力解法)--力扣

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 目录 1. 题目 2. 解法(快慢“指针”) 3. 源码 4. 小结 1. 题目 给你一个数组 nums 和一个值 val&#xff0c;你需要原地移除所有数值等于 val 的元素。元素的顺…

YOLOv10改进,YOLOv10改进主干网络为GhostNetV2(华为的轻量化架构)

摘要 摘要:轻量级卷积神经网络(CNN)专为移动设备上的应用而设计,具有更快的推理速度。卷积操作只能在窗口区域内捕捉局部信息,这限制了性能的进一步提升。将自注意力引入卷积可以很好地捕捉全局信息,但会极大地拖累实际速度。本文提出了一种硬件友好的注意力机制(称为 D…

PHP安装后Apache无法运行的问题

问题 按照网上教程php安装点击跳转教程&#xff0c;然后修改Apache的httpd.conf文件&#xff0c;本来可以运行的Apache&#xff0c;无法运行了 然后在"C:\httpd-2.4.62-240904-win64-VS17\Apache24\logs\error.log"&#xff08;就是我下载Apache的目录下的logs中&am…

多线程——认识线程(Thread)

目录 前言 一、第一个多线程程序 1.程序编写 2.介绍jconsole 二、创建线程 1.继承Thread类 ①重写run方法 ②重写run方法&#xff0c;使用匿名内部类 2.实现Runnable接口 ①重写run方法 ②重写run方法&#xff0c;使用匿名内部类 ③使用 lambda 表达式 三、多线程…

解决MySQL报Incorrect datetime value错误

目录 一、前言二、问题分析三、解决方法 一、前言 欢迎大家来到权权的博客~欢迎大家对我的博客进行指导&#xff0c;有什么不对的地方&#xff0c;我会及时改进哦~ 博客主页链接点这里–>&#xff1a;权权的博客主页链接 二、问题分析 这个错误通常出现在尝试将一个不…

OpenCV学堂 | YOLOv8官方团队宣布YOLOv11 发布了

本文来源公众号“OpenCV学堂”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;YOLOv8官方团队宣布YOLOv11 发布了 引言 YOLO11是Ultralytics YOLO系列实时目标检测器的最新迭代版本&#xff0c;它以尖端的准确性、速度和效率重新…

Mybatis-Plus新花样(一)

一. ActiveRecord Active Record(活动记录)&#xff0c;是一种领域模型模式&#xff0c;特点是一个模型类对应关系型数据库中的一个表&#xff0c;而模型类的一个实例对应表中的一行记录。 在MyBatisPlus中&#xff0c;AR模式即在实体类中封装了对数据库的访问&#xff0c;而不…

Qt_绘图

目录 1、绘图核心类 2、QPainter类的使用 2.1 绘制线段 2.2 绘制矩形 2.3 绘制圆形 2.4 绘制文本 3、QPen类的使用 3.1 使用画笔 4、QBrush类的使用 4.1 使用画刷 5、绘制图片 5.1 测试QPixmap 5.1.1 图片移动 5.1.2 图标缩小 5.1.3 旋转图片 5.1.4 将…

比较10大热门低代码开发平台及其适用性

本文介绍10款主流低代码开发平台&#xff0c;包括ZohoCreator、OutSystems、Mendix等&#xff0c;它们各具特色&#xff0c;如定制能力强、集成方便、全栈开发等&#xff0c;适合不同企业快速构建应用程序&#xff0c;提升开发效率。 一、Zoho Creator Zoho Creator低代码开发…

回溯大总结

目录 0、基础什么是回溯&#xff1f;回溯法解决的问题回溯模板 1、组合问题77. 组合216.组合总和III17. 电话号码的字母组合39. 组合总和&#xff1a;40.组合总和II 0、基础 什么是回溯&#xff1f; 回溯是一种穷举的搜索算法&#xff0c;并不是一个高效的算法&#xff0c;当…

9.数据结构与算法-单链表,循环链表和双向链表的比较////顺序表和链表的比较

单链表&#xff0c;循环链表和双向链表的时间效率比较 顺序表和链表的区别 存储密度

坡印廷矢量(也叫功率流密度,对面积积分就是功率)

坡印廷矢量在静电场&#xff0c;静磁场&#xff0c;恒定电流的电场&#xff0c;和时变电磁场中的表达式不同。 我们看时变电磁场的坡印廷矢量 坡印廷矢量就等于这个&#xff0c;其中的电场和磁场是实数表示的 坡印廷矢量用复数形式的场求 这里的E和H是复数表示的场&#xff0…