前言
DevEco Studio版本:4.0.0.600
WanAndroid的API链接:玩Android 开放API-玩Android - wanandroid.com
其他篇文章参考:
1、WanAndroid(鸿蒙版)开发的第一篇
2、WanAndroid(鸿蒙版)开发的第二篇
3、WanAndroid(鸿蒙版)开发的第三篇
4、WanAndroid(鸿蒙版)开发的第四篇
5、WanAndroid(鸿蒙版)开发的第五篇
效果
项目页面实现
从UI效果上我们知道是可滑动的tab,切换tab时内容切换,因此通过Tabs组件实现
参考链接:OpenHarmony Tabs
因为项目模块有对BaseLibrary模块的引用,在oh-package.json5添加对其引用
1、Tabs列表实现(ProjectList)
build() { Tabs({ barPosition: BarPosition.Start, controller: this.tabsController, }) { ForEach(this.projectListData, (item: ProjectListItemBean) => { TabContent() { TabContentLayout({ tabId: item.id, onDataFinish: () => { this.onDataFinish() } }) } .padding({ left: 12, right: 12 }) .tabBar(new SubTabBarStyle(item.name)) }, (item: ProjectListItemBean) => item.name) } .width('100%') .height('100%') .barMode(BarMode.Scrollable) }
2、TabContentLayout列表内容实现
import { HttpManager, RefreshController, RefreshListView, RequestMethod } from '@app/BaseLibrary'; import LogUtils from '@app/BaseLibrary/src/main/ets/utils/LogUtils'; import { TabContentItemBean } from '../bean/TabContentItemBean'; import { TabContentBean } from '../bean/TabContentBean'; import router from '@ohos.router'; const TAG = 'TabContentLayout--- '; @Component export struct TabContentLayout { @State controller: RefreshController = new RefreshController() @State tabContentItemData: Array = []; @State pageNum: number = 1 //从1开始 @State isRefresh: boolean = true @Prop tabId: number private onDataFinish: () => void //数据加载完成回调 aboutToAppear() { LogUtils.info(TAG, "tabId: " + this.tabId) this.getTabContentData() } private getTabContentData() { LogUtils.info(TAG, "pageNum: " + this.pageNum) HttpManager.getInstance() .request({ method: RequestMethod.GET, header: { "Content-Type": "application/json" }, url: `https://www.wanandroid.com/project/list/${this.pageNum}/json?cid=${this.tabId}` }) .then((result: TabContentBean) => { 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.tabContentItemData = result.data.datas } else { this.tabContentItemData = this.tabContentItemData.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() }) } build() { RefreshListView({ list: this.tabContentItemData, controller: this.controller, refreshLayout: (item: TabContentItemBean, index: number): void => this.itemLayout(item, index), onItemClick: (item: TabContentItemBean, index: number) => { LogUtils.info(TAG, "点击了:index: " + index + " item: " + item) router.pushUrl({ url: 'pages/WebPage', params: { title: item.title, uriLink: item.link } }, router.RouterMode.Single) }, onRefresh: () => { //下拉刷新 this.isRefresh = true this.pageNum = 0 this.getTabContentData() }, onLoadMore: () => { //上拉加载 this.isRefresh = false this.pageNum++ this.getTabContentData() } }) } @Builder itemLayout(item: TabContentItemBean, index: number) { RelativeContainer() { //封面 Image(item.envelopePic) .alt($r('app.media.ic_default_cover')) .width(110) .height(160) .borderRadius(5) .id('imageEnvelope') .alignRules({ top: { anchor: '__container__', align: VerticalAlign.Top }, left: { anchor: '__container__', align: HorizontalAlign.Start } }) //title //标题 Text(item.title) .fontColor('#333333') .fontWeight(FontWeight.Bold) .maxLines(2) .textOverflow({ overflow: TextOverflow.Ellipsis }) .fontSize(18) .margin({ left: 15 }) .maxLines(2) .textOverflow({ overflow: TextOverflow.Ellipsis }) .id("textTitle") .alignRules({ top: { anchor: '__container__', align: VerticalAlign.Top }, left: { anchor: 'imageEnvelope', align: HorizontalAlign.End }, right: { anchor: '__container__', align: HorizontalAlign.End } }) //描述 Text(item.desc) .fontColor('#666666') .fontSize(16) .id("textDesc") .margin({ left: 15, top: 15 }) .maxLines(4) .textOverflow({ overflow: TextOverflow.Ellipsis }) .alignRules({ top: { anchor: 'textTitle', align: VerticalAlign.Bottom }, left: { anchor: 'imageEnvelope', align: HorizontalAlign.End }, right: { anchor: '__container__', align: HorizontalAlign.End } }) //时间 Text(item.niceDate + " " + "作者:" + item.author) .fontColor('#666666') .fontSize(14) .margin({ left: 15 }) .id("textNiceDate") .alignRules({ bottom: { anchor: '__container__', align: VerticalAlign.Bottom }, left: { anchor: 'imageEnvelope', align: HorizontalAlign.End } }) } .width('100%') .height(180) .padding(10) .margin({ left: 10, right: 10, top: 6, bottom: 6 }) .borderRadius(10) .backgroundColor(Color.White) } }
3、项目页面对布局引用
import { LoadingDialog } from '@app/BaseLibrary'; import LogUtils from '@app/BaseLibrary/src/main/ets/utils/LogUtils'; import { ProjectList } from './widget/ProjectList'; @Component export struct ProjectPage { @State projectLoadDataStatus: boolean = false aboutToAppear() { //弹窗控制器,显示 this.dialogController.open() LogUtils.info("33333333333 ProjectPage aboutToAppear执行了") } private dialogController = new CustomDialogController({ builder: LoadingDialog(), customStyle: true, alignment: DialogAlignment.Center }) build() { Column() { ProjectList({ onDataFinish: () => { this.dialogController.close() this.projectLoadDataStatus = true } }) } .visibility(this.projectLoadDataStatus ? Visibility.Visible : Visibility.Hidden) .width('100%') .height('100%') } }
4、页面初始化获取Tabs数据
aboutToAppear() { this.getProjectListData() }
5、根据选中的Tab获取对应Tab的内容数据
aboutToAppear() { LogUtils.info(TAG, "tabId: " + this.tabId)//选中的tab的id this.getTabContentData() }
源代码地址:WanAndroid_Harmony: WanAndroid的鸿蒙版本