鸿蒙学习实战之路-Reader Kit文本缩放因子监听最佳实践
最近好多朋友问我:"西兰花啊,我用Reader Kit做的阅读器,在智慧多窗模式下字体突然变得不对劲了,咋整?"害,这问题我太熟了!这就是文本缩放因子在搞鬼 o(╯□╰)o
今天这篇,我就手把手带你解决Reader Kit在多窗、分屏等场景下文本缩放的问题,教你怎么监听缩放因子变化并自动更新页面排版,全程不超过10分钟(不含调试时间)~
一、问题出在哪?
在智慧多窗、分屏等场景下,系统会调整文本缩放因子Display.scaledDensity属性。如果你的阅读器没有监听这个变化,就会出现字体大小不对、排版混乱的问题。
简单来说,就是你的阅读器还在用旧的缩放因子,但系统已经换了新的,就像你还在用去年的日历一样,肯定不对劲 _
解决思路很简单:
- 监听文本缩放因子变化
- 对比系统值和当前值
- 如果不一致,更新ReaderSetting并重新排版
二、需要用到的接口
咱们做这个功能,主要需要用到几个接口:
| 接口名 | 描述 |
|---|---|
| display.on | 监听屏幕显示属性变化,相当于安装个"监控摄像头"~ |
| display.off | 取消监听,相当于关掉"监控摄像头"~ |
| setPageConfig | 设置或修改页面排版属性,相当于重新排版引擎~ |
| AppStorage | 应用级状态管理,相当于"广播站",在页面间传递信号~ |
| @StorageLink | 监听AppStorage状态变化,相当于"收音机",接收信号并执行操作~ |
三、开发准备
在开始之前,你需要先按照之前的教程构建一个基本的阅读器,就像要先有房子才能装监控一样 _
如果没有构建阅读器,可以先去看看"构建阅读器"那篇文章。
四、具体实现步骤
1. 导入相关模块
首先,咱们需要导入需要的模块:
typescript
import { display } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';
就像炒菜前要先备好调料一样,先把工具都准备好~
2. 在阅读页监听缩放因子变化
在阅读器页面的aboutToAppear生命周期中注册监听,在aboutToDisappear中取消监听:
typescript
@Entry
@Component
struct Reader {
private screenDensityCallBack: Callback<number> | null = null;
aboutToAppear(): void {
this.registerScreenDensityChange();
hilog.info(0x0000, 'testTag',
'aboutToAppear : current scaledDensity = ' + this.readerSetting.scaledDensity + ', change scaledDensity = ' +
display.getDefaultDisplaySync().scaledDensity);
}
/**
* 注册文本缩放因子变化监听
*/
registerScreenDensityChange() {
this.screenDensityCallBack = (data: number) => {
let displaySync = display.getDefaultDisplaySync();
let scaledDensity = displaySync.scaledDensity;
// 对比系统值和当前值
if (scaledDensity !== this.readerSetting.scaledDensity) {
// 通过AppStorage设置标记
AppStorage.setOrCreate('isDensityChange', true);
// 退出阅读页
this.getUIContext().getRouter().back();
}
}
display.on('change', this.screenDensityCallBack);
}
aboutToDisappear(): void {
// 记得取消监听,不然会有内存泄漏
display.off('change', this.screenDensityCallBack);
}
build() {
// 阅读器UI实现
}
}
🥦 西兰花警告 :
我有个朋友忘记在aboutToDisappear中取消监听,结果内存泄漏,debug了半天才发现!血泪教训啊朋友们!
3. 在上级页面监听变化并重新进入阅读页
在上级页面(比如Index)中使用@StorageLink监听变化,当缩放因子改变时自动重新进入阅读页:
typescript
import { hilog } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct Index {
/**
* 系统字体缩放因子是否发生变化,如果变化需要重启阅读器
*/
@StorageLink('isDensityChange') isDensityChange: boolean = false;
onPageShow(): void {
// 文本缩放因子变化需要重新打开书籍
if (this.isDensityChange) {
this.jumper();
AppStorage.setOrCreate('isDensityChange', false);
}
}
private jumper() {
this.getUIContext().getRouter().pushUrl({ url: "pages/Reader" }).catch(() => {
hilog.error(0x0000, 'testTag', 'pushUrl failed');
});
}
build() {
// 上级页面UI实现
}
}
🥦 西兰花小贴士 :
记得在重新进入后把isDensityChange设为false,不然会一直重复进入阅读页,死循环就麻烦了 o(╯□╰)o
4. 保存和恢复阅读进度
重新进入阅读页时,需要保存和恢复阅读进度。可以参考"阅读进度通知"章节的内容:
typescript
// 退出前保存进度
// 在Reader页面的aboutToDisappear或back方法中保存
// 重新进入时恢复进度
// 在Reader页面的aboutToAppear中通过startPlay接口继续阅读
这样用户就不会因为缩放因子变化而丢失阅读进度,体验会好很多 _
五、完整流程总结
整个监听和更新的流程就像这样:
- 用户进入阅读页,注册缩放因子监听
- 用户切换到多窗/分屏模式,系统改变缩放因子
display.on回调触发,检测到缩放因子变化- 设置
isDensityChange标记,退出阅读页 - 上级页面的
onPageShow检测到标记变化 - 自动重新进入阅读页,使用新的缩放因子重新排版
- 恢复阅读进度,用户继续阅读
整个流程无缝衔接,用户几乎感觉不到有什么变化,就是字体和排版自动适配了 (┓( ´∀` )┏
六、常见问题
Q1: 为什么不直接在阅读页更新缩放因子?
A: 因为ReaderKit的setPageConfig需要在页面重新加载后才能生效,直接更新可能不会立即反映到UI上。所以采用了退出重进的方式。
Q2: 会影响阅读体验吗?
A: 不会!因为我们保存了阅读进度,重新进入后会自动跳转到原来的位置,用户几乎感觉不到有变化。
Q3: 除了智慧多窗,还有哪些场景会触发?
A: 分屏、悬浮窗、系统字体大小调整等场景都可能触发缩放因子变化,所以监听是很有必要的。
七、文档资源
官方文档链接:
八、总结
监听文本缩放因子变化是Reader Kit开发中的一个重要功能,特别是在多窗、分屏等场景下。
核心要点:
- 使用
display.on监听缩放因子变化 - 通过
AppStorage在页面间传递状态 - 检测到变化后退出重进,重新排版
- 保存和恢复阅读进度,保证用户体验
🥦 西兰花警告 :
记得在aboutToDisappear中取消监听,不然会有内存泄漏!这个坑我已经替你踩过了 o(╥﹏╥)o
下一步行动
建议你:
- 先在阅读器中添加缩放因子监听
- 测试多窗、分屏场景下的效果
- 完善阅读进度保存和恢复功能
- 优化重新进入时的动画效果
记住,不教理论,只给你能跑的代码和避坑指南! _
我是盐焗西兰花,
不教理论,只给你能跑的代码和避坑指南。
下期见!🥦