HarmonyOS NEXT 阅读翻页方式案例

2024-05-15 10:04

本文主要是介绍HarmonyOS NEXT 阅读翻页方式案例,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

介绍

本示例展示手机阅读时左右翻页,上下翻页,覆盖翻页的功能。

效果图预览

img

使用说明

  1. 进入模块即是左右翻页模式。
  2. 点击屏幕中间区域弹出上下菜单。
  3. 点击设置按钮,弹出翻页方式切换按钮,点击可切换翻页方式。
  4. 左右翻页方式可点击翻页,也可滑动翻页,点击屏幕左边1/3区域向左翻页,点击中间1/3区域弹出菜单,点击屏幕右边1/3区域向右翻页。
  5. 上下翻页方式只可上下滑动翻页。
  6. 覆盖翻页方式可点击翻页,也可滑动翻页,点击屏幕左边1/3区域向左翻页,点击中间1/3区域弹出菜单,点击屏幕右边1/3区域向右翻页。

实现思路

本例涉及的关键特性和实现方案如下:

场景一: 左右翻页方式通过swiper+lazyforeach+cachecount实现按需加载。

实现步骤:

  1. aboutToAppear()方法中通过pushItem向后加载数据,addItem向前加载数据。

  2. 使用Swiper组件和LazyForEach将数据源中的每条数据存放于Text组件中,Swiper向左或向右滑动的效果就是左右翻页的效果。

  3. 需要网络加载时可在BasicDataSourcegetData方法中进行。当index等于0向前申请网络数据,当index等于this.totalCount() - 1时向后请求网络数据。

  4. 请求完数据后可通过push方法将数据插入到队尾,通过unshift插入到队头,具体可参考BasicDataSourcepushItemaddItem方法。

    源码参考:
    LeftRightFlipPage.ets
    BasicDataSource.ets。

 Swiper(this.swiperController) { /*** TODO: 高性能知识点: 使用了cachedCount设置预加载的Text的数量,只在LazyForEach中生效,设置该属性后会缓存cachedCount个Text,LazyForEach超出显示和缓存范围的Text会被释放。* 使用cachedCount参数的例子:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/ui-ts-performance-improvement-recommendation-0000001477981001-V2*/LazyForEach(this.data, (item: string) => {Text($r(item))...}, (item: string) => item)}// TODO:知识点:index设置当前在容器中显示的子组件的索引值。设置小于0或大于等于子组件数量时,按照默认值0处理。.index(this.currentPageNum - CONFIGURATION.PAGEFLIPPAGECOUNT).width($r('app.string.pageflip_full_size')).height($r('app.string.pageflip_full_size')).indicator(false).cachedCount(CONFIGURATION.PAGEFLIPCACHECOUNT)...
aboutToAppear(): void {/*** 请求网络数据之后可以通过this.data.addItem(new Item('app.string.content' + i.toString()));的方法插入到数据源的开头形成新的数据源。* 请求网络数据之后可以通过this.data.pushItem(new Item('app.string.content' + i.toString()));的方法插入到数据源的末尾形成新的数据源。*/for (let i = CONFIGURATION.PAGEFLIPPAGESTART; i <= CONFIGURATION.PAGEFLIPPAGEEND; i++) {this.data.pushItem(STRINGCONFIGURATION.PAGEFLIPRESOURCE + i.toString());}
}
public getData(index: number): string {/*** TODO:知识点:1.当index等于this.totalCount() - 1时向后请求网络数据。当index等于0时向前请求网络数据。* TODO:知识点:2.新请求到的数据可以通过push插入到队尾,通知listeners刷新添加可参考pushItem方法。如果想要插到队头可以通过unshift插入到队头,通知listeners刷新添加可参考addItem方法。*/return this.elements[index];
}
场景二: 上下翻页方式通过list+lazyforeach+cachecount实现按需加载。

实现步骤:

  1. aboutToAppear()方法中通过pushItem向后加载数据,addItem向前加载数据。

  2. 使用List组件和LazyForEach将数据源中的每条数据存放于Text组件中,List向上或向下滑动的效果就是上下翻页的效果。

  3. 需要网络加载时可在BasicDataSourcegetData方法中进行。当index等于0向前申请网络数据,当index等于this.totalCount() - 1时向后请求网络数据。

  4. 请求完数据后可通过push方法将数据插入到队尾,通过unshift插入到队头,具体可参考BasicDataSourcepushItemaddItem方法。

    源码参考:
    UpDownFlipPage.ets
    BasicDataSource.ets。

// TODO:知识点:initialIndex设置为负数或超过了当前List最后一个item的索引值时视为无效取值,无效取值按默认值0显示。
List({ initialIndex: this.currentPageNum - CONFIGURATION.PAGEFLIPPAGECOUNT }) {/*** TODO: 高性能知识点: 使用了cachedCount设置预加载的ListItem的数量,只在LazyForEach中生效,设置该属性后会缓存cachedCount个ListItem,LazyForEach超出显示和缓存范围的ListItem会被释放。* 使用cachedCount参数的例子:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/ui-ts-performance-improvement-recommendation-0000001477981001-V2*/LazyForEach(this.data, (item: string) => {ListItem() {Text($r(item))...}}, (item: string) => item)
}
.width($r('app.string.pageflip_bottomview_row_text_width'))
.height($r('app.string.pageflip_full_size'))
.scrollBar(BarState.Off)
.cachedCount(CONFIGURATION.PAGEFLIPCACHECOUNT)
.onScrollIndex((firstIndex: number) => {this.currentPageNum = firstIndex + CONFIGURATION.PAGEFLIPPAGECOUNT;  // 通过onScrollIndex监听当前处于第几页。
})
aboutToAppear(): void {/*** 请求网络数据之后可以通过this.data.addItem(new Item('app.string.content' + i.toString()));的方法插入到数据源的开头形成新的数据源。* 请求网络数据之后可以通过this.data.pushItem(new Item('app.string.content' + i.toString()));的方法插入到数据源的末尾形成新的数据源。*/for (let i = CONFIGURATION.PAGEFLIPPAGESTART; i <= CONFIGURATION.PAGEFLIPPAGEEND; i++) {this.data.pushItem(STRINGCONFIGURATION.PAGEFLIPRESOURCE + i.toString());}
}
public getData(index: number): string {/*** TODO:知识点:1.当index等于this.totalCount() - 1时向后请求网络数据。当index等于0时向前请求网络数据。* TODO:知识点:2.新请求到的数据可以通过push插入到队尾,通知listeners刷新添加可参考pushItem方法。如果想要插到队头可以通过unshift插入到队头,通知listeners刷新添加可参考addItem方法。*/return this.elements[index];
}
场景三: 覆盖翻页方式通过三个Stack组件通过滑动+动画+改变组件内容实现效果。

实现步骤:

  1. Stack组件中布局三个ReaderPagemidPage位于中间可以根据this.offsetX实时translate自己的位置。

  2. 当this.offsetX<0时,translate的x为this.offsetX,midPage向左移动,显现rightPage

  3. 当this.offsetX>0,translate的x为0,midPage不动,leftPage向右滑动。

  4. 将滑动翻页的动画和点击翻页的动画封装在一个闭包中,由isClick来判断是点击翻页还是滑动翻页,由isLeft来判断点击翻页中是向左翻页还是向右翻页。

  5. 确定翻页时将this.offsetX设置为this.screenW或者-this.screenW。translate移动加上动画效果就会产生覆盖翻页的效果。

  6. 最终滑动动画结束时this.offsetX都会被置为0,leftPage和midPage回归原位。

  7. 当动画结束时由于翻页会让this.currentPageNum加一或减一,根据相应的页数来加载三个content相应的内容。

    源码参考:
    CoverFlipPage.ets。

Stack() {ReaderPage({ content: this.rightPageContent }); // 当midPage向左滑时,rightPage开始显现。ReaderPage({ content: this.midPageContent })/** TODO: 知识点:* 当this.offsetX<0时,translate的x为this.offsetX,midPage向左移动,显现rightPage。* 当this.offsetX>0,translate的x为CONFIGURATION.PAGEFLIPZERO,midPage不动,leftPage向右滑动。*/.translate({x: this.offsetX >= CONFIGURATION.PAGEFLIPZERO ? CONFIGURATION.PAGEFLIPZERO : this.offsetX,y: CONFIGURATION.PAGEFLIPZERO,z: CONFIGURATION.PAGEFLIPZERO}).width(this.screenW);ReaderPage({ content: this.leftPageContent }) // TODO: 知识点:在midPage的左边,当向右滑时,跟随this.offsetX向右滑动。.translate({x: -this.screenW + this.offsetX});
}
private clickAnimateTo(isClick: boolean, isLeft?: boolean) {animateTo({duration: CONFIGURATION.PAGEFLIPTOASTDURATION,curve: Curve.EaseOut,onFinish: () => {/** TODO: 知识点:this.currentPageNum加一或者减一后修改组件的内容。* 右滑:1. 恢复页面原始状态 2. 修改组件的内容为 page1 = content1-1, page2 = content2-1,page3 = content3-1* 左滑:1. 恢复页面原始状态 2. 修改组件的内容为 page1 = content1+1, page2 = content2+1,page3 = content3+1*/if (this.offsetX > CONFIGURATION.PAGEFLIPRIGHTFLIPOFFSETX && this.currentPageNum !== CONFIGURATION.PAGEFLIPPAGESTART) {this.currentPageNum -= CONFIGURATION.PAGEFLIPPAGECOUNT;} else if (this.offsetX < CONFIGURATION.PAGEFLIPLEFTFLIPOFFSETX && this.currentPageNum !== CONFIGURATION.PAGEFLIPPAGEEND) {this.currentPageNum += CONFIGURATION.PAGEFLIPPAGECOUNT;}this.offsetX = CONFIGURATION.PAGEFLIPZERO;this.simulatePageContent();}}, () => {if (isClick) { // 是否为点击翻页if (isLeft) {this.offsetX = this.screenW; // TODO: 知识点:右滑距离变为一个屏幕宽度,ReaderPage就会向右移动一个屏幕宽度,加上动画,形成了覆盖翻页的效果。} else {this.offsetX = -this.screenW; // TODO: 知识点:左滑距离变为一个屏幕宽度,ReaderPage就会向左移动一个屏幕宽度,加上动画,形成了覆盖翻页的效果。}} else { // 滑动翻页if (this.offsetX > CONFIGURATION.PAGEFLIPRIGHTFLIPOFFSETX && this.currentPageNum !== CONFIGURATION.PAGEFLIPPAGESTART) {this.offsetX = this.screenW;} else if (this.offsetX < CONFIGURATION.PAGEFLIPLEFTFLIPOFFSETX && this.currentPageNum !== CONFIGURATION.PAGEFLIPPAGEEND) {this.offsetX = -this.screenW;} else {this.offsetX = CONFIGURATION.PAGEFLIPZERO; // 当位于第一页和末尾页,移动距离设为0,无法翻页。}}});
}
// 模拟书页内容,可以在此进行网络请求。
simulatePageContent() {this.leftPageContent = STRINGCONFIGURATION.PAGEFLIPRESOURCE + (this.currentPageNum - CONFIGURATION.PAGEFLIPPAGECOUNT).toString();this.midPageContent = STRINGCONFIGURATION.PAGEFLIPRESOURCE + (this.currentPageNum).toString();this.rightPageContent = STRINGCONFIGURATION.PAGEFLIPRESOURCE + (this.currentPageNum + CONFIGURATION.PAGEFLIPPAGECOUNT).toString();
}

工程结构&模块类型

   pageflip                                         // har包|---common|   |---Constants.ets                            // 常量 |---components|   |---mainpage                                 |       |---PageFlip.ets                         // 主页面|---datasource|   |---BasicDataSource.ets                      // Basic数据控制器|---view|   |---BottomView.ets                           // 底部菜单视图|   |---CoverFlipPage.ets                        // 覆盖翻页视图|   |---LeftRightFlipPage.ets                    // 左右翻页视图|   |---TopView.ets                              // 顶部菜单视图|   |---UpDownFlipPage.ets                       // 上下翻页视图

模块依赖

routermodule

高性能知识点

本例使用了onActionUpdate函数。该函数是系统高频回调函数,避免在函数中进行冗余或耗时操作,例如应该减少或避免在函数打印日志,会有较大的性能损耗。

本示例使用了LazyForEach进行数据懒加载,List布局时会根据可视区域按需创建ListItem组件,并在ListItem滑出可视区域外时销毁以降低内存占用。

本示例使用了cachedCount设置预加载的ListItem的数量,只在LazyForEach中生效,设置该属性后会缓存cachedCount个ListItem,LazyForEach超出显示和缓存范围的ListItem会被释放。

参考资料

LazyForEach:数据懒加载

ZIndex

List

Swiper

@Link装饰器:父子双向同步

最后分享一份鸿蒙(HarmonyOS)开发学习指南需要的可以扫码免费领取!!!

《鸿蒙(HarmonyOS)开发学习指南》

第一章 快速入门

1、开发准备

2、构建第一个ArkTS应用(Stage模型)

3、构建第一个ArkTS应用(FA模型)

4、构建第一个JS应用(FA模型)

5、…

图片

第二章 开发基础知识

1、应用程序包基础知识

2、应用配置文件(Stage模型)

3、应用配置文件概述(FA模型)

4、…

图片

第三章 资源分类与访问

1、 资源分类与访问

2、 创建资源目录和资源文件

3、 资源访问

4、…

图片

第四章 学习ArkTs语言

1、初识ArkTS语言

2、基本语法

3、状态管理

4、其他状态管理

5、渲染控制

6、…

图片

第五章 UI开发

1.方舟开发框架(ArkUI)概述

2.基于ArkTS声明式开发范式

3.兼容JS的类Web开发范式

4…

图片

第六章 Web开发

1.Web组件概述

2.使用Web组件加载页面

3.设置基本属性和事件

4.在应用中使用前端页面JavaScript

5.ArkTS语言基础类库概述

6.并发

7…

图片

11.网络与连接

12.电话服务

13.数据管理

14.文件管理

15.后台任务管理

16.设备管理

17…

图片

第七章 应用模型

1.应用模型概述

2.Stage模型开发指导

3.FA模型开发指导

4…

这篇关于HarmonyOS NEXT 阅读翻页方式案例的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/991522

相关文章

Debezium 与 Apache Kafka 的集成方式步骤详解

《Debezium与ApacheKafka的集成方式步骤详解》本文详细介绍了如何将Debezium与ApacheKafka集成,包括集成概述、步骤、注意事项等,通过KafkaConnect,D... 目录一、集成概述二、集成步骤1. 准备 Kafka 环境2. 配置 Kafka Connect3. 安装 D

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

SQL 中多表查询的常见连接方式详解

《SQL中多表查询的常见连接方式详解》本文介绍SQL中多表查询的常见连接方式,包括内连接(INNERJOIN)、左连接(LEFTJOIN)、右连接(RIGHTJOIN)、全外连接(FULLOUTER... 目录一、连接类型图表(ASCII 形式)二、前置代码(创建示例表)三、连接方式代码示例1. 内连接(I

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

JS 实现复制到剪贴板的几种方式小结

《JS实现复制到剪贴板的几种方式小结》本文主要介绍了JS实现复制到剪贴板的几种方式小结,包括ClipboardAPI和document.execCommand这两种方法,具有一定的参考价值,感兴趣的... 目录一、Clipboard API相关属性方法二、document.execCommand优点:缺点:

Python创建Excel的4种方式小结

《Python创建Excel的4种方式小结》这篇文章主要为大家详细介绍了Python中创建Excel的4种常见方式,文中的示例代码简洁易懂,具有一定的参考价值,感兴趣的小伙伴可以学习一下... 目录库的安装代码1——pandas代码2——openpyxl代码3——xlsxwriterwww.cppcns.c

Deepseek使用指南与提问优化策略方式

《Deepseek使用指南与提问优化策略方式》本文介绍了DeepSeek语义搜索引擎的核心功能、集成方法及优化提问策略,通过自然语言处理和机器学习提供精准搜索结果,适用于智能客服、知识库检索等领域... 目录序言1. DeepSeek 概述2. DeepSeek 的集成与使用2.1 DeepSeek API

CSS弹性布局常用设置方式

《CSS弹性布局常用设置方式》文章总结了CSS布局与样式的常用属性和技巧,包括视口单位、弹性盒子布局、浮动元素、背景和边框样式、文本和阴影效果、溢出隐藏、定位以及背景渐变等,通过这些技巧,可以实现复杂... 一、单位元素vm 1vm 为视口的1%vh 视口高的1%vmin 参照长边vmax 参照长边re