WanAndroid(鸿蒙版)开发的第二篇

news2024/11/25 13:24:25

前言

DevEco Studio版本:4.0.0.600

WanAndroid的API链接:玩Android 开放API-玩Android - wanandroid.com

1、WanAndroid(鸿蒙版)开发的第一篇

其他一些参考点,请参考上面的WanAndroid开发第一篇

效果

首页实现

整体布局分为头部的Banner和底部的列表List,知道了整体的机构我们就来进行UI布局

1、Banner实现

参考华为官方  OpenHarmony Swiper

详细代码:

import router from '@ohos.router';
import { BannerItemBean } from '../bean/BannerItemBean';
import { HttpManager, RequestMethod } from '@app/BaseLibrary';
import LogUtils from '@app/BaseLibrary/src/main/ets/utils/LogUtils';
import { BannerBean } from '../bean/BannerBean';

const TAG = 'Banner--- ';

@Component
export struct Banner {
   @State bannerData: Array<BannerItemBean> = [];
   private swiperController: SwiperController = new SwiperController();
   @State isVisibility: boolean = true
   private onDataFinish: () => void //数据加载完成回调

   aboutToAppear() {
      this.getBannerData()
   }

   private getBannerData() {
      HttpManager.getInstance()
         .request<BannerBean>({
            method: RequestMethod.GET,
            header: { "Content-Type": "application/json" },
            url: 'https://www.wanandroid.com/banner/json', //wanAndroid的API:Banner
         })
         .then((result: BannerBean) => {
            LogUtils.info(TAG, "result: " + JSON.stringify(result))
            if (result.errorCode == 0) {
               this.isVisibility = true
               this.bannerData = result.data
            } else {
               this.isVisibility = false
            }
            this.onDataFinish()
         })
         .catch((error) => {
            LogUtils.info(TAG, "error: " + JSON.stringify(error))
            this.isVisibility = false
            this.onDataFinish()
         })
   }

   build() {
      Swiper(this.swiperController) {
         ForEach(this.bannerData, (banner: BannerItemBean) => {
            Image(banner.imagePath)
               .borderRadius(16)
               .onClick(() => {
                  router.pushUrl({
                     url: 'pages/WebPage',
                     params: {
                        title: banner.title,
                        uriLink: banner.url,
                        isShowCollect: false,
                     }
                  }, router.RouterMode.Single)
               })
         }, (banner: BannerItemBean) => banner.url)
      }
      .margin({ top: 10 })
      .autoPlay(true)
      .interval(1500)
      .visibility(this.isVisibility ? Visibility.Visible : Visibility.None)
      .width('100%')
      .height(150)
   }
}

2、List列表实现

因为是带上拉加载和下拉刷新,参考我之前文章:鸿蒙自定义刷新组件使用_harmoneyos 自定义刷新

详细代码:

import {
   BaseResponseBean,
   Constants,
   HtmlUtils,
   HttpManager,
   RefreshController,
   RefreshListView,
   RequestMethod
} from '@app/BaseLibrary';
import LogUtils from '@app/BaseLibrary/src/main/ets/utils/LogUtils';
import { HomeListItemBean } from '../bean/HomeListItemBean';
import { HomeListBean } from '../bean/HomeListBean';
import router from '@ohos.router';
import promptAction from '@ohos.promptAction';

const TAG = 'HomeList--- ';

@Component
export struct HomeList {
   @State controller: RefreshController = new RefreshController()
   @State homeListData: Array<HomeListItemBean> = [];
   @State pageNum: number = 0
   @State isRefresh: boolean = true
   private onDataFinish: () => void //数据加载完成回调
   @State userName: string = ''
   @State token_pass: string = ''
   @State listCollectState: Array<boolean> = [] //用于存储收藏状态

   aboutToAppear() {
      if (AppStorage.Has(Constants.APPSTORAGE_USERNAME)) {
         this.userName = AppStorage.Get(Constants.APPSTORAGE_USERNAME) as string
      }
      if (AppStorage.Has(Constants.APPSTORAGE_TOKEN_PASS)) {
         this.token_pass = AppStorage.Get(Constants.APPSTORAGE_TOKEN_PASS) as string
      }
      this.getHomeListData()
   }

   /**
    * 获取列表数据
    */
   private getHomeListData() {
      HttpManager.getInstance()
         .request<HomeListBean>({
            method: RequestMethod.GET,
            header: {
               "Content-Type": "application/json",
               "Cookie": `loginUserName=${this.userName}; token_pass=${this.token_pass}`
            },
            url: `https://www.wanandroid.com/article/list/${this.pageNum}/json` //wanAndroid的API:Banner
         })
         .then((result: HomeListBean) => {
            LogUtils.info(TAG, "result: " + JSON.stringify(result))
            if (this.isRefresh) {
               this.controller.finishRefresh()
            } else {
               this.controller.finishLoadMore()
            }
            if (result.errorCode == 0) {
               if (this.isRefresh) {
                  this.homeListData = result.data.datas
                  for (let i = 0; i < this.homeListData.length; i++) {
                     this.listCollectState[i] = this.homeListData[i].collect
                  }
               } else {
                  this.homeListData = this.homeListData.concat(result.data.datas)
               }
            }
            this.onDataFinish()
         })
         .catch((error) => {
            LogUtils.info(TAG, "error: " + JSON.stringify(error))
            if (this.isRefresh) {
               this.controller.finishRefresh()
            } else {
               this.controller.finishLoadMore()
            }
            this.onDataFinish()
         })
   }

   @Builder
   itemLayout(item: HomeListItemBean, index: number) {
      RelativeContainer() {
         //作者或分享人
         Text(item.author.length > 0 ? "作者:" + item.author : "分享人:" + item.shareUser)
            .fontColor('#666666')
            .fontSize(14)
            .id("textAuthor")
            .alignRules({
               top: { anchor: '__container__', align: VerticalAlign.Top },
               left: { anchor: '__container__', align: HorizontalAlign.Start }
            })

         Text(item.superChapterName + '/' + item.chapterName)
            .fontColor('#1296db')
            .fontSize(14)
            .id("textChapterName")
            .alignRules({
               top: { anchor: '__container__', align: VerticalAlign.Top },
               right: { anchor: '__container__', align: HorizontalAlign.End }
            })

         //标题
         Text(HtmlUtils.formatStr(item.title))
            .fontColor('#333333')
            .fontWeight(FontWeight.Bold)
            .maxLines(2)
            .textOverflow({
               overflow: TextOverflow.Ellipsis
            })
            .fontSize(20)
            .margin({ top: 10 })
            .id("textTitle")
            .alignRules({
               top: { anchor: 'textAuthor', align: VerticalAlign.Bottom },
               left: { anchor: '__container__', align: HorizontalAlign.Start }
            })

         //更新时间
         Text("时间:" + item.niceDate)
            .fontColor('#666666')
            .fontSize(14)
            .id("textNiceDate")
            .alignRules({
               bottom: { anchor: '__container__', align: VerticalAlign.Bottom },
               left: { anchor: '__container__', align: HorizontalAlign.Start }
            })

         //收藏状态
         Image(this.listCollectState[index] ? $r('app.media.ic_select_collect') : $r('app.media.ic_normal_collect'))
            .width(26)
            .height(26)
            .id('imageCollect')
            .alignRules({
               bottom: { anchor: '__container__', align: VerticalAlign.Bottom },
               right: { anchor: '__container__', align: HorizontalAlign.End }
            })
            .onClick(() => {
               this.setCollectData(item.id, index)
            })
      }
      .width('100%')
      .height(120)
      .padding(10)
      .margin({ left: 10, right: 10, top: 6, bottom: 6 })
      .borderRadius(10)
      .backgroundColor(Color.White)
   }

   build() {
      RefreshListView({
         list: this.homeListData,
         controller: this.controller,
         isEnableLog: true,
         refreshLayout: (item: HomeListItemBean, index: number): void => this.itemLayout(item, index),
         onItemClick: (item: HomeListItemBean, index: number) => {
            LogUtils.info(TAG, "点击了:index: " + index + " item: " + item)
            router.pushUrl({
               url: 'pages/WebPage',
               params: {
                  title: item.title,
                  uriLink: item.link,
                  isShowCollect: true,
                  isCollect: this.listCollectState[index]
               }
            }, router.RouterMode.Single)
         },
         onRefresh: () => {
            //下拉刷新
            this.isRefresh = true
            this.pageNum = 0
            this.getHomeListData()
         },
         onLoadMore: () => {
            //上拉加载
            this.isRefresh = false
            this.pageNum++
            this.getHomeListData()
         }
      })
   }

   /**
    * 设置收藏和取消收藏状态
    * @param id  文章id
    * @param index  数据角标
    */
   private setCollectData(id: number, index: number) {
      let collect = this.listCollectState[index]
      let urlLink = collect ? `https://www.wanandroid.com/lg/uncollect_originId/${id}/json` : `https://www.wanandroid.com/lg/collect/${id}/json` //取消收藏和收藏接口

      HttpManager.getInstance()
         .request<BaseResponseBean>({
            method: RequestMethod.POST,
            header: {
               "Content-Type": "application/json",
               "Cookie": `loginUserName=${this.userName}; token_pass=${this.token_pass}`
            },
            url: urlLink //wanAndroid的API:收藏和取消收藏
         })
         .then((result: BaseResponseBean) => {
            LogUtils.info(TAG, "收藏  result: " + JSON.stringify(result))
            if (result.errorCode == 0) {
               this.listCollectState[index] = !this.listCollectState[index]
               promptAction.showToast({ message: collect ? "取消收藏成功" : "收藏成功" })
            } else {
               promptAction.showToast({ message: result.errorMsg })
            }
         })
         .catch((error) => {
            LogUtils.info(TAG, "收藏  error: " + JSON.stringify(error))
         })
   }
}

注意点:就是在获取List数据时,通过WanAndroid的API知道要想获取收藏状态需要传入用户登录时的Cookie,但是鸿蒙没有像Android那样的Cookie处理,只能通过在登录的时候获取loginUserName和token_pass然后在请求时将这两个参数添加到请求头中,实现如下图:

这两个参数获取参考第一篇的文章。

3、将两个视图整合

详细代码:

import { Banner } from './widget/Banner';
import { HomeList } from './widget/HomeList';
import { LoadingDialog } from '@app/BaseLibrary';
import LogUtils from '@app/BaseLibrary/src/main/ets/utils/LogUtils';

@Component
export struct HomePage {
   @State bannerLoadDataStatus: boolean = false
   @State HomeListLoadDataStatus: boolean = false

   aboutToAppear() {
      //弹窗控制器,显示
      this.dialogController.open()
   }

   private dialogController = new CustomDialogController({
      builder: LoadingDialog(),
      customStyle: true,
      alignment: DialogAlignment.Center, // 可设置dialog的对齐方式,设定显示在底部或中间等,默认为底部显示
   })

   build() {
      Column() {
         Banner({ onDataFinish: () => {
            this.bannerLoadDataStatus = true
            LogUtils.info("33333333333 Banner  bannerLoadDataStatus: " + this.bannerLoadDataStatus + "  HomeListLoadDataStatus: " + this.HomeListLoadDataStatus)
            if (this.bannerLoadDataStatus && this.HomeListLoadDataStatus) {
               this.dialogController.close()
            }
         } })
         HomeList({ onDataFinish: () => {
            this.HomeListLoadDataStatus = true
            LogUtils.info("33333333333 HomeList  bannerLoadDataStatus: " + this.bannerLoadDataStatus + "  HomeListLoadDataStatus: " + this.HomeListLoadDataStatus)
            if (this.bannerLoadDataStatus && this.HomeListLoadDataStatus) {
               this.dialogController.close()
            }
         } }).flexShrink(1)
            .margin({ top: 10 })
      }
      .visibility(this.bannerLoadDataStatus && this.HomeListLoadDataStatus ? Visibility.Visible : Visibility.Hidden)
      .width('100%')
      .height('100%')
   }
}

源代码地址:WanAndroid_Harmony: WanAndroid的鸿蒙版本

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

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

相关文章

ARM学习(25)链接装载高阶认识

ARM学习&#xff08;25&#xff09;链接装载高阶认识 1、例子引出 笔者先引入几个编译链接的例子来介绍一下&#xff1a; 声明无效&#xff1a;declared implicitly&#xff1f;&#xff0c;属于编译错误还是链接错误&#xff1f; 编译阶段的错误&#xff0c;属于编译错误&am…

《量子计算:下一个大风口,还是一个热炒概念?》

引言 量子计算,作为一项颠覆性的技术,一直以来备受关注。它被认为是未来计算领域的一次革命,可能改变我们对计算能力和数据处理的理解。然而,随着技术的不断进步和商业应用的探索,人们开始思考,量子计算到底是一个即将到来的大风口,还是一个被过度炒作的概念? 量子计…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的夜间车辆检测系统(深度学习代码+UI界面+训练数据集)

摘要&#xff1a;开发夜间车辆检测系统对于自动驾驶技术具有关键作用。本篇博客详细介绍了如何运用深度学习构建一个夜间车辆检测系统&#xff0c;并提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并对比了YOLOv7、YOLOv6、YOLOv5&#xff0c;展示了不同模型间…

Hadoop学习1:概述、单体搭建、伪分布式搭建

文章目录 概述基础知识Hadoop组件构成Hadoop配置文件 环境准备配置Hadoop配置下载配置环境变量 Hadoop运行模式Standalone Operation&#xff08;本地&#xff09;官方DemoWordCount单词统计Demo Pseudo-Distributed Operation&#xff08;伪分布式模式&#xff09;配置修改启动…

vscode使用remote-ssh免密连接服务器

你还在使用XShell、Hyper、FinalShell等等SSH客户端软件吗&#xff0c;作为前端的我们&#xff0c;一直在用的功能强大的开发工具vscode&#xff0c;早已实现SSH连接功能&#xff08;借助官方提供的插件&#xff09;。而且更加好用&#xff0c;可以直接打开服务器上的文件&…

使用npm版本管理工具解决npm 的EACCES permissions errors when installing packages globally错误

EACCES错误通常表示“权限被拒绝”&#xff0c;意味着您没有足够的权限来执行某个操作。在计算机领域&#xff0c;尤其是在文件系统和程序安装中&#xff0c;这个错误很常见。以下是可能导致EACCES错误的原因以及相应的解决方法&#xff1a; 文件系统权限&#xff1a;当您尝试…

❤️算法笔记❤️-(每日一刷-141、环形链表)

文章目录 题目思路解法 题目 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接…

【调参】如何为神经网络选择最合适的学习率lr-LRFinder-for-Keras

【调参】如何为神经网络选择最合适的学习率lr-LRFinder-for-Keras_学习率选择-CSDN博客文章浏览阅读9.2k次&#xff0c;点赞6次&#xff0c;收藏55次。keras 版本的LRFinder&#xff0c;借鉴 fast.ai Deep Learning course。前言学习率lr在神经网络中是最难调的全局参数&#x…

YOLOv9改进 添加可变形注意力机制DAttention

一、Deformable Attention Transformer论文 论文地址:arxiv.org/pdf/2201.00520.pdf 二、Deformable Attention Transformer注意力结构 Deformable Attention Transformer包含可变形注意力机制,允许模型根据输入的内容动态调整注意力权重。在传统的Transformer中,注意力是…

Qt 如何搭建lua的运行环境

一、lua简介 Lua 是一种强大的、高效的、轻量级的、可嵌入的脚本语言。它支持过程&#xff08;procedural&#xff09;编程、面向对象编程、函数式编程以及数据描述。Lua 是动态类型的&#xff0c;运行速度快&#xff0c;支持自动内存管理&#xff0c;因此被广泛用于配置、脚本…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Select)

提供下拉选择菜单&#xff0c;可以让用户在多个选项之间选择。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 无 接口 Select(options: Array<SelectOption>) 参数&#xff1a;…

HUAWEI 华为交换机 配置 MAC 地址漂移检测示例

组网需求 如 图 2-17 所示&#xff0c;网络中两台 LSW 间网线误接形成了网络环路&#xff0c;引起 MAC 地址发生漂 移、MAC 地址表震荡。 为了能够及时检测网络中出现的环路&#xff0c;可以在 Switch 上配置 MAC 地址漂移检测功能&#xff0c; 通过检测是否发生MAC 地址漂移…

网络学习:BGP路径属性分类

目录 前言&#xff1a; 路径属性分类 公认必遵 公认任意 可选过渡 可选非过渡 前言&#xff1a; 在默认情况下&#xff0c;到达同一目的地&#xff0c;BGP只走单条路径&#xff0c;并不会在多条路径之间执行负载均衡。对于IGP路由协议&#xff0c;当有多条路径可以到达同…

丘一丘正则表达式

正则表达式(regular expression,regex,RE) 正则表达式是一种用来简洁表达一组字符串的表达式正则表达式是一种通用的字符串表达框架正则表达式是一种针对字符串表达“简洁”和“特征”思想的工具正则表达式可以用来判断某字符串的特征归属 正则表达式常用操作符 操作符说明实…

[vscode]将命令行参数传递给调试目标

一、简介 本文介绍了在vscode中使用cmake工具时&#xff0c;如何传递参数给编译目标的方法。 前提&#xff1a;使用vscodecmake编译C/C程序。 二、方法 在.vscode/目录下新建settings.json文件&#xff0c;并将待传底的参数写在 cmake.debugConfig里。 下面介绍了一个示例&a…

DAY14二叉树迭代遍历

二叉树前序迭代法遍历 前序遍历是中左右&#xff0c;每次先处理的是中间节点&#xff0c;那么先将根节点放入栈中&#xff0c;然后将右孩子加入栈&#xff0c;再加入左孩子。 为什么要先加入 右孩子&#xff0c;再加入左孩子呢&#xff1f; 因为这样出栈的时候才是中左右的顺…

Stable Diffusion 如何写好提示词(Prompt)

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 大家好&#xff0c;我是水滴~~ 本文深入探讨了如何撰写出优质的提示词&#xff0c;内容涵盖多个维度&#xff1a;提示词的多样化分类、模型应用中的经典提示词案例、提供丰富资源的提示词参考…

基于STM32的智慧农业管理系统设计与实现

文章目录 一、前言1.1 项目介绍【1】项目功能【2】设计实现的功能【3】项目硬件模块组成 1.2 设计思路1.3 传感器功能介绍1.4 开发工具的选择 二、EMQX开源MQTT服务器框架三、购买ECS云服务器3.1 登录官网3.2 购买ECS服务器3.3 配置安全组3.4 安装FinalShell3.5 远程登录到云服…

Java代码审计工程师直播第六期

本期直播课程将深入探讨Java代码审计的关键概念和技术。涵盖课题包括安全漏洞分析、代码审查方法、常见漏洞案例分析等。学员将通过实例掌握代码审计实战技能&#xff0c;提升对Java应用程序安全的认知和技能水平。 课程大小&#xff1a;6.1G 课程下载&#xff1a;https://do…

Docker 容器化技术:构建高效、可移植的开发环境和部署流程|Docker 三要素

镜像、容器、镜像仓库是 Docker 中最核心的三个概念&#xff0c;组成了 Docker 的整个生命周期。 &#xff08;镜像、容器、镜像仓库三者运行关系&#xff09; 1、镜像 镜像是 Docker 的核心元素质疑&#xff0c;作为容器运行的基础&#xff0c;Docker Hub 官网提供了庞大的镜…