文章目录
- [1 -> 概述](#1 -> 概述)
- [2 -> 背景:ArkWeb PDF预览能力概览](#2 -> 背景:ArkWeb PDF预览能力概览)
-
- [2.1 -> 基础配置](#2.1 -> 基础配置)
- [2.2 -> 三种PDF加载方式](#2.2 -> 三种PDF加载方式)
- [2.3 -> 预览参数配置](#2.3 -> 预览参数配置)
- [3 -> `onPdfLoadEvent`:PDF加载状态回调(API 20+)](#3 ->
onPdfLoadEvent:PDF加载状态回调(API 20+)) -
- [3.1 -> 事件定义与参数说明](#3.1 -> 事件定义与参数说明)
- [3.2 -> 完整代码示例](#3.2 -> 完整代码示例)
- [3.3 -> 实际应用场景](#3.3 -> 实际应用场景)
- [4 -> `onPdfScrollAtBottom`:滚动到底部事件回调(API 20+)](#4 ->
onPdfScrollAtBottom:滚动到底部事件回调(API 20+)) -
- [4.1 -> 事件定义与参数说明](#4.1 -> 事件定义与参数说明)
- [4.2 -> 完整代码示例](#4.2 -> 完整代码示例)
- [4.3 -> 实际应用场景](#4.3 -> 实际应用场景)
- [5 -> 综合应用:两个事件的协同使用](#5 -> 综合应用:两个事件的协同使用)
- [6 -> 总结](#6 -> 总结)

1 -> 概述
在移动应用开发中,PDF文档预览是一项非常高频的需求------合同展示、电子发票预览、电子书阅读、产品说明书浏览等场景都离不开PDF的支持。HarmonyOS ArkWeb组件早在API 9版本便已提供基础的PDF预览能力,支持加载网络、应用沙箱内和本地资源等多种来源的PDF文档。然而,在API 20版本之前,开发者只能被动地展示PDF内容,无法感知PDF是否加载成功、是否因为网络异常或文件损坏而加载失败,也难以准确判断用户是否已经滚动到PDF文档的末尾。
从API version 20开始,ArkWeb针对PDF浏览能力进行了重要增强,新增了两个关键回调事件:
onPdfLoadEvent:通知应用PDF页面的加载状态,包括加载成功或加载失败,并提供详细的错误信息onPdfScrollAtBottom:通知应用用户已将PDF页面滚动到底部
这两个事件从底层解决了PDF预览场景中"状态不可知"的痛点,让开发者能够基于用户行为构建更完整、更智能的产品体验。本文将围绕这两个新增特性展开详细讲解,涵盖API用法、代码示例和典型应用场景。
2 -> 背景:ArkWeb PDF预览能力概览
在深入讲解这两个新增事件之前,有必要先回顾一下ArkWeb组件的基础PDF预览能力,以便理解本次增强在整个功能架构中的位置。
2.1 -> 基础配置
使用Web组件预览PDF,需要进行以下基础配置:
- 开启DOM存储权限 :PDF预览页面会使用
window.localStorage记录侧导航栏的展开状态,因此必须设置domStorageAccess(true) - 网络访问权限 (仅网络PDF需要):在
module.json5中配置ohos.permission.INTERNET权限 - 文件访问权限 (仅应用沙箱PDF需要):设置
fileAccess(true)
2.2 -> 三种PDF加载方式
ArkWeb支持通过三种方式加载PDF文档:
方式一:加载网络PDF文档
arkts
Web({
src: 'https://www.example.com/test.pdf',
controller: this.controller
})
.domStorageAccess(true)
方式二:加载应用沙箱内PDF文档
arkts
Web({
src: this.getUIContext().getHostContext()!.filesDir + '/test.pdf',
controller: this.controller
})
.domStorageAccess(true)
.fileAccess(true)
方式三:加载本地资源PDF文档(支持两种格式)
arkts
// 格式一:使用resource协议
Web({
src: 'resource://rawfile/test.pdf',
controller: this.controller
})
.domStorageAccess(true)
// 格式二:使用$rawfile语法
Web({
src: $rawfile('test.pdf'),
controller: this.controller
})
.domStorageAccess(true)
2.3 -> 预览参数配置
在加载PDF文档时,还可以通过URL参数控制初始显示状态,这些参数通过URL片段(#)传递:
| 参数 | 描述 | 示例 |
|---|---|---|
page=pagenum |
指定初始页码(从1开始) | #page=3 |
zoom=scale |
设置缩放比例 | #zoom=50 |
toolbar=1或0 |
1显示顶部工具栏,0隐藏 | #toolbar=0 |
navpanes=1或0 |
1显示侧边导航窗格,0隐藏 | #navpanes=0 |
pdfbackgroundcolor=color |
指定PDF背景色(从HarmonyOS 6.0开始支持),color为六位十六进制RGB值 | #pdfbackgroundcolor=ffffff |
使用示例:
arkts
// 加载第3页并设置50%缩放
this.controller.loadUrl("https://www.example.com/test.pdf#page=3&zoom=50");
// 隐藏工具栏和导航窗格
this.controller.loadUrl("resource://rawfile/test.pdf#toolbar=0&navpanes=0");
关于动态切换PDF文档 :需要特别注意的是,WebOptions的第一个参数变量src不能通过状态变量(如@State)动态更改地址,如需切换PDF文档,必须调用loadUrl()接口重新加载。
arkts
// 切换到新的PDF文档
this.controller.loadUrl("https://www.example.com/new.pdf");
// 切换到沙箱内其他文档
this.controller.loadUrl(this.getUIContext().getHostContext()!.filesDir + "/new.pdf");
3 -> onPdfLoadEvent:PDF加载状态回调(API 20+)
3.1 -> 事件定义与参数说明
onPdfLoadEvent是API version 20新增的PDF加载状态回调事件,用于通知应用PDF页面的加载结果,包括加载成功和加载失败两种情况。
事件回调函数的参数类型为OnPdfLoadEvent,包含以下关键字段:
| 字段 | 类型 | 说明 |
|---|---|---|
url |
string | 当前加载的PDF文档URL地址 |
result |
number | 加载结果码。通常0表示成功,非0表示失败(具体错误码含义可查阅官方文档) |
3.2 -> 完整代码示例
以下是一个完整的示例,演示如何监听PDF加载状态,并根据加载结果给出相应的用户反馈:
arkts
import { webview } from '@kit.ArkWeb';
@Entry
@Component
struct PdfPreviewWithLoadEvent {
controller: webview.WebviewController = new webview.WebviewController();
@State loadStatus: string = '等待加载...';
@State isLoadError: boolean = false;
build() {
Column() {
// 状态展示区域
Row() {
Text(`加载状态:${this.loadStatus}`)
.fontSize(14)
.fontColor(this.isLoadError ? '#FF4444' : '#4CAF50')
}
.padding(12)
.width('100%')
.backgroundColor(this.isLoadError ? '#FFEBEE' : '#E8F5E9')
// Web组件展示PDF
Web({
src: 'https://www.example.com/test.pdf',
controller: this.controller
})
.domStorageAccess(true)
.onPdfLoadEvent((eventInfo: OnPdfLoadEvent) => {
console.info(`PDF加载事件触发,URL: ${eventInfo.url}, result: ${eventInfo.result}`);
if (eventInfo.result === 0) {
// 加载成功
this.loadStatus = '加载成功';
this.isLoadError = false;
console.info('PDF文档加载成功,可以开始预览');
} else {
// 加载失败
this.loadStatus = `加载失败,错误码:${eventInfo.result}`;
this.isLoadError = true;
console.error(`PDF文档加载失败,错误码:${eventInfo.result},URL:${eventInfo.url}`);
}
})
.width('100%')
.height('80%')
}
}
}
3.3 -> 实际应用场景
onPdfLoadEvent的应用价值非常明确:
场景一:加载失败提示与重试机制
当用户网络不稳定或PDF文件损坏时,加载失败是一个高频场景。通过监听onPdfLoadEvent,可以在加载失败时自动弹出友好提示,并提供重试按钮,而不是让用户面对一个空白的Web视图。
arkts
.onPdfLoadEvent((eventInfo: OnPdfLoadEvent) => {
if (eventInfo.result !== 0) {
// 显示加载失败弹窗,提供重试选项
this.showRetryDialog(eventInfo.url);
}
})
场景二:大数据量的PDF预加载
在电商、医疗、金融等需要展示大量PDF文档的场景中,可以在用户浏览文档列表时提前预加载下一个PDF。监听加载成功事件后,可以将预加载的PDF内容缓存起来,提升用户切换文档时的响应速度。
场景三:加载耗时统计与性能监控
开发侧可以在onPdfLoadEvent中记录PDF从发起加载到完成的时间,用于监控特定文档的加载性能,辅助优化文档的分发策略。
arkts
.onPdfLoadEvent((eventInfo: OnPdfLoadEvent) => {
if (eventInfo.result === 0) {
const loadTime = Date.now() - this.startTime;
console.info(`PDF加载完成,耗时:${loadTime}ms,文件:${eventInfo.url}`);
// 上报性能数据
this.reportPerformance('pdf_load_time', loadTime);
}
})
4 -> onPdfScrollAtBottom:滚动到底部事件回调(API 20+)
4.1 -> 事件定义与参数说明
onPdfScrollAtBottom是API version 20新增的滚动到底部回调事件,用于通知应用用户已将PDF页面滚动到文档末尾。
在API 20版本之前,由于PDF是以插件的形式在Web组件中加载的,传统的onScroll事件无法监听到PDF内部滚动条的滚动。开发者只能通过onOverScroll回调中的偏移量来粗略判断PDF是否到达顶端或底端,但这种方式不仅精度有限,而且需要自行处理偏移量阈值判断,代码复杂且不可靠。
onPdfScrollAtBottom的出现从根本上解决了这一问题------ArkWeb底层直接提供了PDF滚动到底部的精准通知。
事件回调函数的参数类型为OnPdfScrollEvent,包含以下关键字段:
| 字段 | 类型 | 说明 |
|---|---|---|
url |
string | 当前滚动事件所对应的PDF文档URL地址 |
4.2 -> 完整代码示例
以下是一个完整的示例,演示如何监听PDF滚动到底部事件,并在到达底部时触发相应的业务逻辑:
arkts
import { webview } from '@kit.ArkWeb';
@Entry
@Component
struct PdfPreviewWithScrollEvent {
controller: webview.WebviewController = new webview.WebviewController();
@State scrollMessage: string = '滚动到底部时将自动触发';
@State bottomReachedCount: number = 0;
build() {
Column() {
// 提示区域
Row() {
Text(this.scrollMessage)
.fontSize(14)
.fontColor('#666')
}
.padding(12)
.width('100%')
.justifyContent(FlexAlign.Center)
// 已触发次数统计
if (this.bottomReachedCount > 0) {
Text(`已触发滚动到底部事件 ${this.bottomReachedCount} 次`)
.fontSize(12)
.fontColor('#999')
.padding({ bottom: 8 })
}
// Web组件展示PDF
Web({
src: 'https://www.example.com/long-document.pdf',
controller: this.controller
})
.domStorageAccess(true)
.onPdfScrollAtBottom((eventInfo: OnPdfScrollEvent) => {
console.info(`PDF滚动到底部,URL: ${eventInfo.url}`);
// 更新UI状态
this.bottomReachedCount++;
this.scrollMessage = `已滚动到底部!第${this.bottomReachedCount}次触发`;
// 模拟震动反馈(可选)
// this.getUIContext().getPromptAction().showToast({ message: '已滚动到底部' });
})
.width('100%')
.height('80%')
}
}
}
4.3 -> 实际应用场景
onPdfScrollAtBottom的应用价值同样十分广泛:
场景一:电子书阅读与分页标记
在电子书应用中,当用户阅读完一本书的最后一页时,可以自动记录"已读完"标记,并推荐下一本书或展示评分界面。
arkts
.onPdfScrollAtBottom((eventInfo: OnPdfScrollEvent) => {
// 记录用户已阅读完毕
this.markBookAsCompleted(this.currentBookId);
// 弹出读后感或评分弹窗
this.showRatingDialog();
})
场景二:合同签署场景中的"签字确认"
在电子合同签署流程中,通常要求用户在阅读完合同全文后才能在签字区签名。通过监听滚动到底部事件,可以动态解锁签字按钮,确保用户确实浏览了完整内容。
arkts
.onPdfScrollAtBottom((eventInfo: OnPdfScrollEvent) => {
// 解锁签字按钮
this.isSignEnabled = true;
// 显示提示信息
this.showToast('您已阅读完整合同内容,现在可以进行签字');
})
场景三:无限滚动与分页加载
在需要展示大量PDF文档的场景中,可以在用户滚动到当前PDF末尾时自动加载下一个PDF,实现连续阅读的无缝体验。
arkts
.onPdfScrollAtBottom((eventInfo: OnPdfScrollEvent) => {
if (this.hasNextDocument()) {
// 自动加载下一个PDF
const nextPdfUrl = this.getNextDocumentUrl();
this.controller.loadUrl(nextPdfUrl);
this.showToast('正在加载下一篇文档...');
}
})
5 -> 综合应用:两个事件的协同使用
在实际开发中,onPdfLoadEvent和onPdfScrollAtBottom往往需要协同工作。以下是一个综合示例,展示如何同时使用这两个事件构建一个完整的PDF阅读体验:
arkts
import { webview } from '@kit.ArkWeb';
@Entry
@Component
struct ComprehensivePdfReader {
controller: webview.WebviewController = new webview.WebviewController();
@State isLoading: boolean = true;
@State loadSuccess: boolean = false;
@State errorMessage: string = '';
@State hasReachedBottom: boolean = false;
@State showBottomIndicator: boolean = false;
build() {
Column() {
// 加载状态指示器
if (this.isLoading) {
LoadingProgress()
.width(40)
.height(40)
.color('#007DFF')
}
// 加载失败时的错误展示
if (!this.loadSuccess && !this.isLoading && this.errorMessage) {
Column() {
Text('📄 PDF加载失败')
.fontSize(16)
.fontWeight(FontWeight.Medium)
Text(this.errorMessage)
.fontSize(14)
.fontColor('#999')
.margin({ top: 8 })
Button('重新加载')
.onClick(() => {
this.isLoading = true;
this.loadSuccess = false;
this.errorMessage = '';
this.controller.loadUrl('https://www.example.com/test.pdf');
})
.margin({ top: 16 })
}
.width('100%')
.height('60%')
.justifyContent(FlexAlign.Center)
}
// PDF预览
if (!this.errorMessage || (this.loadSuccess && !this.isLoading)) {
Web({
src: 'https://www.example.com/test.pdf',
controller: this.controller
})
.domStorageAccess(true)
.onPdfLoadEvent((eventInfo: OnPdfLoadEvent) => {
this.isLoading = false;
if (eventInfo.result === 0) {
this.loadSuccess = true;
this.errorMessage = '';
console.info(`PDF加载成功: ${eventInfo.url}`);
} else {
this.loadSuccess = false;
this.errorMessage = `加载失败,错误码:${eventInfo.result}`;
console.error(`PDF加载失败: ${eventInfo.url}, result: ${eventInfo.result}`);
}
})
.onPdfScrollAtBottom((eventInfo: OnPdfScrollEvent) => {
if (!this.hasReachedBottom) {
this.hasReachedBottom = true;
this.showBottomIndicator = true;
console.info(`PDF滚动到底部: ${eventInfo.url}`);
// 显示提示并自动隐藏
setTimeout(() => {
this.showBottomIndicator = false;
}, 2000);
}
})
.width('100%')
.height('80%')
}
// 滚动到底部提示浮层
if (this.showBottomIndicator) {
Text('📌 已阅读至文档末尾')
.fontSize(14)
.fontColor('#FFFFFF')
.backgroundColor('rgba(0,0,0,0.7)')
.borderRadius(20)
.padding({ left: 16, right: 16, top: 8, bottom: 8 })
.position({ x: '50%', y: '90%' })
.translate({ x: '-50%', y: 0 })
}
}
}
}
6 -> 总结
HarmonyOS 6.0(API version 20)中,ArkWeb组件的PDF预览能力在"状态感知"维度上迈出了重要一步。onPdfLoadEvent让开发者能够准确获知PDF的加载结果------无论是成功还是失败,都可以基于此构建完善的异常处理与用户反馈机制。onPdfScrollAtBottom则从根本上解决了PDF内部滚动状态不可知的问题,使电子书阅读、合同签署、连续阅读等场景的交互设计变得更加优雅和可靠。
从开发者的视角来看,这两个事件的接入成本很低------只需在Web组件上添加对应的回调函数即可。结合已有的PDF参数配置(如页码跳转、缩放、工具栏隐藏、背景色设置等),ArkWeb已经能够覆盖绝大多数PDF预览需求。随着HarmonyOS生态的持续演进,ArkWeb在PDF能力方面的进一步增强值得持续关注。
感谢各位大佬支持!!!
互三啦!!!