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

news2024/12/25 9:31:31

时至今日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 = true
  imgList: 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_data
    if (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.coloradmin.cn/o/2183286.html

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

相关文章

【2023工业3D异常检测文献】M3DM: 基于混合融合的多模态工业异常检测方法

Multimodal Industrial Anomaly Detection via Hybrid Fusion 1、Background 随着3D传感器的发展&#xff0c;最近发布了具有2D图像和3D点云数据的MVTec-3D AD数据集&#xff0c;促进了多模态工业异常检测的研究。 无监督异常检测的核心思想是找出正常表示与异常之间的差异。…

[云服务器16] 搭建flarum论坛,纯小白向

论&#xff1a; 如何才能正确搭建Flarum论坛&#xff1f; 先看成品&#xff08;当然还没搭好&#xff0c;直达车&#xff09;&#xff1a; 那么&#xff0c;怎么才能部署如此之好の论坛呢&#xff1f; 本期主要讲述正确搭建Flarum的方法&#xff0c;100%成功&#xff0c;即使…

【STM32单片机_(HAL库)】4-3-4【定时器TIM】测量按键按下时间实现3

1.硬件 STM32单片机最小系统按键模块 2.软件 定时器HAL驱动层文件添加ic驱动文件添加GPIO常用函数定时器输入捕获实验配置步骤main.c程序 #include "sys.h" #include "delay.h" #include "led.h" #include "uart1.h" #include &qu…

vue3 环境配置vue-i8n国际化

一.依赖和插件的安装 主要是vue-i18n和 vscode的自动化插件i18n Ally https://vue-i18n.intlify.dev/ npm install vue-i18n10 pnpm add vue-i18n10 yarn add vue-i18n10 vscode在应用商城中搜索i18n Ally&#xff1a;如图 二.实操 安装完以后在对应项目中的跟package.jso…

谈谈英国论文写作复合句式的运用

每次在写英国论文的时候&#xff0c;为了力求表达准确&#xff0c;很多留学生会选择使用简单句型来完成整篇文章的写作。这样的写作虽然可以完整地表达论文的意思&#xff0c;但是只用简单句完成全文&#xff0c;可能在grammar部分的评分会比较低。因此学会运用复合句型也成为留…

QT中的按钮控件和comboBox控件和spinBox控件无法点击的bug

如图所示的.ui&#xff0c;执行却无法点击&#xff0c;需要删除布局&#xff0c;重新布局&#xff0c;并且QGroupBox放到后面。

每天五分钟深度学习pytorch:基于pytorch搭建一元线性回归模型

本文重点 前面我们学习了很多零散的知识,比如优化器,学习率,损失函数,反向传播参数计算等等,从本节课程起,我们将这些知识总结起来,本节课程我们看一下,如何才能通过pytorch搭建一元线性回归模型 什么是一元线性回归模型? 一元线性回归是只有一个自变量 (自变量x和…

RabbitMQ的相关题

一、 MQ的作⽤及应⽤场景 类似问题: 项⽬什么场景下使⽤到了MQ, 为什么需要MQ? RabbitMQ 的作⽤?使⽤场景有哪些? RabbitMQ…

python之with

with上下文管理是什么呢&#xff1f; 一般都是使用系统提供的一些with语句&#xff0c;列如我要去读取一些数据进行分析&#xff0c;就可以使用with open去读取某些数据&#xff0c;或者我要把一些图片给他保存到某些地方&#xff0c;可以用with给他写入。 上下午管理器with是…

墙绘艺术在线市场:SpringBoot实现指南

2 相关技术 2.1 SSM框架介绍 本课题程序开发使用到的框架技术&#xff0c;英文名称缩写是SSM&#xff0c;在JavaWeb开发中使用的流行框架有SSH、SSM、SpringMVC等&#xff0c;作为一个课题程序采用SSH框架也可以&#xff0c;SSM框架也可以&#xff0c;SpringMVC也可以。SSH框架…

精选算法入门——day1

题目一 题干 在一个二维数组中&#xff08;每个一维数组的长度相同&#xff09;&#xff0c;每一行都按照从左到右递增的顺序排序&#xff0c;每一列都按照从上到下递增的顺序排序。请完成一个函数&#xff0c;输入这样的一个二维数组和一个整数&#xff0c;判断数组中是否含…

【STM32单片机_(HAL库)】4-3-1【定时器TIM】串口打印功能打开

1.硬件 STM32单片机最小系统CH340模块 2.软件 main.c程序 #include "sys.h" #include "delay.h" #include "led.h" #include "uart1.h"int main(void) {HAL_Init(); /* 初始化HAL库 */stm32_clock_init(R…

常见的RTSP播放器有哪些?

VLC播放器 特点&#xff1a;VLC 是一款功能强大、跨平台的多媒体播放器&#xff0c;支持多种音频和视频格式以及流媒体协议&#xff0c;包括 RTSP。它具有广泛的解码器支持&#xff0c;能播放大多数常见的视频和音频格式。其开源特性使得它拥有活跃的开发者社区&#xff0c;不断…

【教学类-59-01】20241001双面五星红旗国旗(中2班)

背景需求&#xff1a; 国庆在即&#xff0c;怎么能不做一面五星红旗呢&#xff1f; 【教学类-39】A4红纸-国旗灯笼纸模&#xff08;庆祝中华人民共和国成立74周年&#xff09;_a4 打印 灯笼-CSDN博客文章浏览阅读626次。【教学类-39】A4红纸-国旗灯笼纸模&#xff08;庆祝中华…

车辆重识别(注意力 U-Net:学习在哪些区域寻找胰腺)论文阅读2024/10/01

什么是注意力机制&#xff1f; 什么是加性注意力&#xff1f; 大致说一下流程&#xff1a; 对于一张特征图来说&#xff0c;对于这张图中的每一个像素向量&#xff08;例如a&#xff09;&#xff0c;计算该向量与所有像素向量的相似度&#xff0c;对这些相似度进行激活函数…

nvm实现nodejs版本管理

nvm相关操作 1. nvm的作用2. 下载nvm之前的操作3. 下载nvm3.1 zip不同的名称区别 4. 验证是否安装成功5. 配置镜像,提高下载速度6. 安装nodeJS7. 查看目前已经安装的版本8.安装成功后npm无法使用9. 卸载指定node版本10. 切换node版本11.NVM常用命令 1. nvm的作用 nvm是一个方便…

24-10-1-读书笔记(二十一)-《契诃夫文集》(四)下([俄] 契诃夫 [译] 汝龙) 我爱你,娜坚卡。

文章目录 《契诃夫文集》&#xff08;四&#xff09;下&#xff08;[俄] 契诃夫 [译] 汝龙 &#xff09;目录阅读笔记记录总结 《契诃夫文集》&#xff08;四&#xff09;下&#xff08;[俄] 契诃夫 [译] 汝龙 &#xff09; 十月第一篇&#xff0c;放假了&#xff0c;挺高兴的&…

如何使用SCCMSecrets识别SCCM策略中潜在的安全问题

关于SCCMSecrets SCCMSecrets是一款针对SCCM策略的安全扫描与检测工具&#xff0c;该工具旨在提供一种有关 SCCM 策略的全面安全检测方法。 该工具可以从各种权限级别执行&#xff0c;并将尝试发现与策略分发相关的潜在错误配置。除了分发点上托管的包脚本外&#xff0c;它还将…

螺狮壳里做道场:老破机搭建的私人数据中心---Centos下Docker学习01(环境准备)

1 准备工作 由于创建数据中心需要安装很多服务器&#xff0c;这些服务器要耗费很所物理物理计算资源、存储资源、网络资源和软件资源&#xff0c;作为穷学生只有几百块的n手笔记本&#xff0c;不可能买十几台服务器来搭建数据中心&#xff0c;也不愿意跑实验室&#xff0c;想躺…

信息安全数学基础(23)一般二次同余式

前言 信息安全数学基础中的一般二次同余式是数论和密码学中的一个重要概念&#xff0c;它涉及到了二次方程、模运算以及同余关系等多个方面。 一、定义 设m是正整数&#xff0c;a,b,c是整数&#xff0c;且a0&#xff0c;则形如ax2bxc≡0(modm)的同余式称为模m的二次同余式。…