鸿蒙NEXT开发实战往期必看文章:
一分钟了解”纯血版!鸿蒙HarmonyOS Next应用开发!
HarmonyOS NEXT应用开发(5.0版)高频场景解决方案分享1-100篇,持续更新中~-
HarmonyOS NEXT应用开发案例实践总结合(持续更新......)
HarmonyOS NEXT应用开发性能优化实践总结(持续更新......)
简介
本文档主要面向小说应用的开发人员,指导开发者使用推荐的解决方案快速推进小说类应用的HarmonyOS适配工作。本文档立足于解决伙伴需求,提供了完整的小说类应用HarmonyOS实现方案,实现方案包括阅读器排版渲染、翻页动效实现(覆盖翻页、左右滑动翻页、上下滑动翻页)。本文档包括效果展示、场景说明、场景优化方案介绍等内容,关键能力的接入附带有详细的流程介绍和关键代码示例,力求为开发者的顺利接入提供最大程度的便捷。
效果展示
场景使用说明
适用范围
本场景解决方案适用于小说类应用HarmonyOS化。有阅读页或组件切换动效需求的开发者均可参照本文档快速接入。
场景优势
本场景的优势主要体现在功能和技术方案方面,应用使用HarmonyOS的解决方案,可以快速实现主要功能的开发。具体优势如下:
(1)阅读器排版方案清楚明晰,主要包括Canvas绘制,背景色、字号、屏幕亮度等阅读器属性修改等功能。
(2)页面前后页预渲染,当前页出现变化时,实时更新上一页与下一页的内容,并在后台预渲染,使翻页动效更加流畅。
场景分析
本文档主要介绍小说类应用场景小说阅读器实现及翻页动效设计,相关子场景、介绍、实现说明参考下表:
编号 | 分类 | 子场景 | 描述 | 实现说明 |
---|---|---|---|---|
1 | 小说阅读器实现 | 阅读器的排版渲染 | 阅读页面的内容加载,阅读器亮度、背景色、字体翻页模式的属性设置 | Canvas绘制、设置项数据双向绑定、组件属性设置 |
2 | 翻页动效设计 | 覆盖翻页 | 用户左右拖动屏幕,页面可同步覆盖翻页 | 滑动窗口预渲染机制、组件平移算法 |
3 | 左右滑动翻页 | 用户左右拖动屏幕,页面可同步滑动翻页 | 滑动窗口预渲染机制、组件平移算法 | |
4 | 上下滑动翻页 | 用户上下拖动屏幕,页面可同步上下滑动翻页 | 滑动窗口预渲染机制、组件平移算法 |
场景介绍
小说阅读器实现
文字页面实现
封装的文字页面子组件,父组件向子组件传递文字起点字符索引并订阅字体大小、页面背景色等属性,子组件负责小说页面的绘制。
@Component
export default struct Reader {
// 背景颜色、字体大小、文字起点索引
@Consume('bgColor') @Watch('onPageChange') bgColor: string;
@Consume('fontSize') @Watch('onPageChange') fontSize: number;
@Prop @Watch('onPageChange') startIndex: number = 0;
...
//绘制函数
drawText(startIndex: number) {
...
}
build() {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) {
Column() {
Canvas(this.context)
.width(Constants.FULL_PERCENT)
.height(Constants.FULL_PERCENT)
.onReady(() => {
this.drawText(this.startIndex);
})
}
.width(Constants.FULL_PERCENT)
}
.height(Constants.FULL_PERCENT)
}
}
阅读器的排版渲染控制
阅读器排版渲染控制支持亮度修改、字体大小修改,背景颜色修改以及翻页类型修改等。
页面设置半模态属性bindSheet,onClick事件判断点击页面中部时显示半模态页面。半模态页面展示页面设置信息,用于修改阅读器的排版属性,数据与父组件之间建立双向绑定,属性修改后传给父组件,父组件再传递给阅读器页面组件,从而实现排版属性实时修改。
build() {
Row() {
...
}
.bindSheet(
$$this.isShow,
this.myBuilder(),
...
)
.backgroundColor(this.bgColor)
}
@Builder
myBuilder() {
Column() {
SheetView()
}
.height(Constants.FULL_PERCENT)
.width(Constants.FULL_PERCENT)
}
翻页动效设计
技术原理示意图
初始状态 | 向左翻页过程 | 向右翻页过程 |
---|---|---|
初始时当前页(Page2)位于视窗顶部,示意图以覆盖翻页为例,上一页(Page1)向左平移出视窗区域,下一页(Page3)位于当前页下方被当前页覆盖。向左滑动时当前页左移,下一页出现在视窗中;向右滑动时,上一页出现在视窗区域覆盖当前页。
文字页面堆叠
Stack容器中存放文字页面,除上下滑动效果外,同一时刻只需要准备当前页、上一页、下一页的渲染即可。当前页面更新,则同步更新上一页、下一页。翻页过程类似滑动窗口,所以只需要三页就可以模拟这个循环。上下滑动翻页区别于其他翻页方式,存在同时展示两页的场景。假设当前页为第三页,向后翻页同时显示三四页时需预渲染第五页,向前翻页同时显示二三页是需预渲染第一页,故最多需要五个页面。
Stack() {
Reader({
startIndex: this.currentStartIndex + this.sumRow * this.rowWord,
})
Reader({
startIndex: this.currentStartIndex
})
.width(this.screenW)
Reader({
startIndex: this.currentStartIndex - this.sumRow * this.rowWord,
})
.translate({
x: -this.screenW + this.offsetX
})
}
场景实现
覆盖翻页
Stack容器中为文字页面组件添加位移属性,与Stack容器滑动窗口的结构对应,PanGesture拖动手势获取横向位移值,通过translate平移属性及显式动效实现实时拖动效果以及手指释放时自动位移的效果。
@Component
export struct CoverFlipView {
...
build() {
Stack() {
Reader({ startIndex: this.currentStartIndex + this.sumRow * this.rowWord })
Reader({ startIndex: this.currentStartIndex })
.translate({ x: this.offsetX >= 0 ? 0 : this.offsetX, y: 0, z: 0 })
Reader({ startIndex: this.currentStartIndex - this.sumRow * this.rowWord })
.translate({ x: -this.screenW + this.offsetX })
}
.gesture(
PanGesture()
.onActionUpdate((event?: GestureEvent) => {
...
// 获取拖动位移,修改文字页面位置
this.offsetX = event.offsetX;
})
.onActionEnd(() => {
// 显式动效实现手指释放后自动位移
animateTo({
...
}, () => {
// 依据当前偏移量,控制翻页方向
if (this.offsetX > 0) {
this.offsetX = this.screenW;
}
if (this.offsetX < 0) {
this.offsetX = -this.screenW;
}
})
})
)
}
}
左右滑动翻页
左右滑动翻页效果和覆盖翻页效果实现方法大体相同。依据PanGesture拖动手势、animateTo显式动效实现左右滑动效果。在初始化页面位置时将下一页平移至当前页右侧,将上一页平移至当前页左侧。执行拖动操作时,控制三个页面的水平位置,实现左右滑动的效果。
@Component
export struct SlideFlipView {
...
build() {
Stack() {
Reader({ startIndex: this.currentStartIndex + this.sumRow * this.rowWord })
.translate({ x: this.offsetX >= 0 ? this.screenW : this.screenW + this.offsetX, y: 0, z: 0 })
Reader({ startIndex: this.currentStartIndex })
.translate({ x: this.offsetX, y: 0, z: 0 })
.width(this.screenW)
Reader({ startIndex: this.currentStartIndex - this.sumRow * this.rowWord })
.translate({ x: this.offsetX >= 0 ? -this.screenW + this.offsetX : -this.screenW, y: 0, z: 0 })
}
.gesture(
// 拖动手势相关参考覆盖翻页
PanGesture()
)
}
}
上下滑动翻页
上下滑动翻页效果区别于其他翻页效果,可能会同时显示两页,故最少要加载当前页及后两页共三页(当前页为首页时),最多加载当前页及前后各两页共五页。参考左右滑动调整纵向滑动,实现上下滑动翻页效果。
@Component
export struct UpDownFlipView {
...
build() {
Stack() {
Reader({ startIndex: this.currentStartIndex + 2 * this.sumRow * this.rowWord })
.translate({ x: 0, y: this.translateY2 + 2 * this.screenH + this.offsetY, z: 0 })
.backgroundColor('gray')
Reader({ startIndex: this.currentStartIndex + this.sumRow * this.rowWord })
.translate({ x: 0, y: this.translateY2 + this.screenH + this.offsetY, z: 0 })
.backgroundColor('gray')
Reader({ startIndex: this.currentStartIndex })
.translate({ x: 0, y: this.translateY2 + this.offsetY, z: 0 })
.backgroundColor('gray')
.width(this.screenW)
if (this.currentPageNum > 1) {
Reader({ startIndex: this.currentStartIndex - this.sumRow * this.rowWord })
.translate({ x: 0, y: this.translateY2 - this.screenH + this.offsetY, z: 0 })
}
if (this.currentPageNum > 2) {
Reader({ startIndex: this.currentStartIndex - 2 * this.sumRow * this.rowWord })
.backgroundColor('gray')
.translate({ x: 0, y: this.translateY2 - 2 * this.screenH + this.offsetY, z: 0 })
}
...
}
.gesture(
PanGesture()
.onActionUpdate((event?: GestureEvent) => {
if (!event) {
return;
}
...
// 获取拖动位移,移动界面
this.offsetY = event.offsetY;
})
...
)
}
}
最后
小编在之前的鸿蒙系统扫盲中,有很多朋友给我留言,不同的角度的问了一些问题,我明显感觉到一点,那就是许多人参与鸿蒙开发,但是又不知道从哪里下手,因为资料太多,太杂,无从选择。有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)文档用来跟着学习是非常有必要的。
如果你是一名有经验的资深Android移动开发、Java开发、前端开发、对鸿蒙感兴趣以及转行人员
→ 鸿蒙HarmonyOS Next 全栈开发学习笔记 希望这一份鸿蒙学习文档能够给大家带来帮助~
这份鸿蒙(HarmonyOS NEXT)包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、(南向驱动、嵌入式等)鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。