鸿蒙学习实战之路-Reader Kit构建阅读器最佳实践
最近好多朋友问我:“西兰花啊,我用Reader Kit获取了书籍信息和目录,可怎么才能真正构建一个能阅读的阅读器啊?” 害,这问题可问对人了!咱们前面做的那些准备工作,就像买菜和切菜,现在终于要下锅炒菜了~今天这篇,我就手把手带你用Reader Kit构建一个完整的阅读器,教你怎么显示书籍内容并实现阅读功能,全程不超过10分钟(不含下载时间)~
鸿蒙学习实战之路-Reader Kit构建阅读器最佳实践
最近好多朋友问我:“西兰花啊,我用Reader Kit获取了书籍信息和目录,可怎么才能真正构建一个能阅读的阅读器啊?” 害,这问题可问对人了!咱们前面做的那些准备工作,就像买菜和切菜,现在终于要下锅炒菜了~
今天这篇,我就手把手带你用Reader Kit构建一个完整的阅读器,教你怎么显示书籍内容并实现阅读功能,全程不超过10分钟(不含下载时间)~
一、构建阅读器的基本流程
咱们先来看个流程图,了解一下整个过程是咋回事:

简单来说,整个流程就像咱们做饭的过程:
- 准备食材(导入相关模块)
- 准备厨具(初始化组件控制器和设置)
- 搭建灶台(构建ReadPageComponent组件)
- 开始炒菜(初始化解析器并启动阅读器)
二、需要用到的接口
咱们做这个功能,主要需要用到5个接口,就像做饭需要用到锅、铲、勺、碗、盘一样:
| 接口名 | 描述 |
|---|---|
| getDefaultHandler | 获取书籍默认解析器,相当于准备好食材处理器 |
| init | 初始化ReadPageComponent控制器,相当于点燃灶台 |
| setPageConfig | 设置页面排版属性,相当于调整火候 |
| registerBookParser | 注册书籍解析器,相当于把食材放进锅里 |
| startPlay | 以指定进度打开书籍,相当于开始炒菜 |
三、具体实现步骤
1. 导入相关模块
首先,咱们得把需要的模块导入进来,就像做饭前先把所有食材和工具都摆出来一样:
// 导入解析能力、页面组件和阅读器控制类
import { bookParser, ReadPageComponent, readerCore } from '@kit.ReaderKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { display } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { common } from '@kit.AbilityKit';
2. 初始化组件控制器和设置
接下来,咱们需要初始化组件控制器、默认设置项,以及定义书籍解析器,就像做饭前先准备好锅碗瓢盆一样:
// 组件控制器,用于调用排版相关能力
private readerComponentController: readerCore.ReaderComponentController = new readerCore.ReaderComponentController();
// 默认设置项,用于初始化阅读器页面的默认属性
private readerSetting: readerCore.ReaderSetting = {
fontName: '系统字体',
fontPath: '',
fontSize: 18,
fontColor: '#000000',
fontWeight: 400,
lineHeight: 1.9,
nightMode: false,
themeColor: 'rgba(248, 249, 250, 1)',
themeBgImg: '',
flipMode: '0',
scaledDensity: display.getDefaultDisplaySync().scaledDensity > 0 ? display.getDefaultDisplaySync().scaledDensity : 1,
viewPortWidth: 1260, // 视口宽度,需要根据设备实际情况获取,否则会导致阅读界面异常
viewPortHeight: 2720, // 视口高度,需要根据设备实际情况获取,否则会导致阅读界面异常
};
// 书籍解析器,用于注册给组件控制器,供排版引擎调用
private bookParserHandler: bookParser.BookParserHandler | null = null;
// 是否正在加载页面(需要等待页面渲染完成再隐藏,避免进入页面会先显示黑屏的问题)
@State isLoading: boolean = true;
3. 构建ReadPageComponent组件
现在,咱们需要构建ReadPageComponent组件,用于显示阅读内容,就像搭建好灶台准备炒菜一样:
build() {
Stack() {
ReadPageComponent({
controller: this.readerComponentController,
readerCallback: (err: BusinessError, data: readerCore.ReaderComponentController) => {
this.readerComponentController = data;
}
})
Row() {
Text('加载中...')
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor(Color.White)
.visibility(this.isLoading ? Visibility.Visible : Visibility.None)
}.width('100%').height('100%')
}
4. 初始化解析器并启动阅读器
最后,咱们需要初始化书籍解析器并启动阅读器,就像把食材放进锅里开始炒菜一样:
aboutToAppear(): void {
// 初始化阅读器
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
let filePath: string = `${context.filesDir}/abc.epub`;
let spineIndex: number = 0;
let domPos: string = '';
this.registerListener();
this.startPlay(filePath, spineIndex, domPos);
}
private registerListener(): void {
this.readerComponentController.on('pageShow', (data: readerCore.PageDataInfo): void => {
hilog.info(0x0000, 'testTag', 'pageshow: data is: ' + JSON.stringify(data));
if (data.state === readerCore.PageState.PAGE_ON_SHOW) {
this.isLoading = false;
}
});
}
private async startPlay(filePath: string, spineIndex: number, domPos: string) {
try {
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
// 组件控制器初始化,用于控制ReadPageComponent调用排版引擎
let initPromise = this.readerComponentController.init(context);
// 初始化书籍解析器
let bookParserHandler = bookParser.getDefaultHandler(filePath);
let result: [bookParser.BookParserHandler, void] = await Promise.all([bookParserHandler, initPromise]);
this.bookParserHandler = result[0];
// 设置默认页面属性,用于排版的默认样式
this.readerComponentController.setPageConfig(this.readerSetting);
// 注册解析能力到控制器中,用于排版引擎的调用
this.readerComponentController.registerBookParser(this.bookParserHandler);
// 调用打开书籍接口,跳章至对应进度
this.readerComponentController.startPlay(spineIndex || 0, domPos);
} catch (err) {
hilog.error(0x0000, 'testTag', 'startPlay: err: ' + JSON.stringify(err));
}
}
aboutToDisappear(): void {
this.readerComponentController.off('pageShow');
// 退出需要释放阅读器实例
this.readerComponentController.releaseBook();
}
四、需要注意的地方
🥦 西兰花警告
-
初始化顺序很重要:
init接口必须在其他接口之前执行,registerBookParser必须在startPlay之前执行,就像做饭时必须先点火再炒菜一样,顺序错了就会出问题~ -
视口尺寸的设置:代码中设置了
viewPortWidth和viewPortHeight,这两个值需要根据设备实际情况获取,否则会导致阅读界面异常,就像炒菜时火候没调好会把菜炒糊一样~ -
资源释放:在
aboutToDisappear中,咱们必须调用releaseBook释放阅读器实例,否则会内存泄漏,就像做完饭要关火一样,不然会有安全隐患~
🥦 西兰花小贴士
-
加载状态的处理:代码中通过
isLoading状态来控制加载提示的显示和隐藏,并且在pageShow事件中才设置为false,这样可以避免进入页面时先显示黑屏的问题,就像炒菜时要等油热了再放菜一样,时机很重要~ -
并发初始化:代码中使用
Promise.all来并发执行init和getDefaultHandler,这样可以提高初始化速度,就像做饭时可以同时切菜和热锅一样,节省时间~
五、下一步行动
现在咱们已经学会了如何构建一个完整的阅读器,接下来可以试试:
- 实现阅读设置功能,比如调整字体大小、颜色、背景等
- 实现翻页效果的切换,比如仿真翻页和滑动翻页
- 实现阅读进度的保存和恢复
📚 推荐资料
我是盐焗西兰花,
不教理论,只给你能跑的代码和避坑指南。
下期见!🥦
更多推荐




所有评论(0)