ArkWeb in HarmonyOS 6.0 adds PDF load success/failure callbacks and bottom-scroll detection in API 20+, solving the long-standing limitation of PDF preview being visible but not observable. This article breaks down loading methods, parameter control, event integration, and real-world implementation patterns. Keywords: ArkWeb, PDF Preview, HarmonyOS 6.0
Technical Specs Snapshot
| Parameter | Description |
|---|---|
| Platform | HarmonyOS 6.0 |
| API Requirement | API 20+ |
| Development Language | ArkTS |
| Core Component | ArkWeb Web component |
| Core Capabilities | PDF preview, load status callbacks, bottom scroll detection |
| Supported Protocols | https://, resource://, $rawfile, local sandbox paths |
| Required Permission | ohos.permission.INTERNET (for network PDFs) |
| Core Dependencies | @kit.ArkWeb, webview.WebviewController |
| Star Count | Not provided in the original article |
AI Visual Insight: This diagram shows how ArkWeb hosts PDF preview rendering inside a Web component. The key takeaway is that PDF event monitoring depends on ArkWeb-native extensions rather than standard web page scroll listeners.
ArkWeb in HarmonyOS 6.0 now provides PDF state observability
PDF preview is a common requirement for contracts, invoices, manuals, and ebooks. Earlier ArkWeb versions already supported basic rendering, but developers could not verify whether a document had actually loaded successfully, nor could they accurately determine whether a user had reached the end.
API 20+ introduces two key events: onPdfLoadEvent and onPdfScrollAtBottom. The first exposes the load result, while the second directly reports whether the document has been scrolled to the end. This gives PDF reading workflows observability for the first time.
The two new events solve different problems
onPdfLoadEvent: Solves the inability to detect blank pages, broken links, or corrupted files.onPdfScrollAtBottom: Solves the fact that internal PDF scrolling cannot be captured by a regularonScrollevent.- Together, they enable a workflow of “read after successful load, then trigger business logic after reading is complete.”
// Core integration for API 20+
Web({ src: pdfUrl, controller: this.controller })
.domStorageAccess(true) // Enable DOM storage, which PDF preview depends on
.onPdfLoadEvent((eventInfo: OnPdfLoadEvent) => {
// Listen for PDF load success or failure
})
.onPdfScrollAtBottom((eventInfo: OnPdfScrollEvent) => {
// Listen for whether the PDF has been scrolled to the bottom
})
This code defines the two key observability entry points for ArkWeb in PDF scenarios.
ArkWeb now supports three types of PDF sources
Before using ArkWeb to preview a PDF, do not skip the basic configuration. Network PDFs require ohos.permission.INTERNET, sandbox files typically require fileAccess(true), and PDF sidebar state depends on domStorageAccess(true).
The three common sources are network URLs, app sandbox files, and in-app raw resources. Together, they cover the three mainstream delivery models: online documents, downloaded cached documents, and bundled static documents.
The three loading methods cover mainstream business entry points
import { webview } from '@kit.ArkWeb';
@Entry
@Component
struct PdfSourceDemo {
controller: webview.WebviewController = new webview.WebviewController();
build() {
Column() {
Button('Load Network PDF')
.onClick(() => {
// Load a remote PDF document
this.controller.loadUrl('https://www.example.com/test.pdf');
})
Button('Load Sandbox PDF')
.onClick(() => {
// Load a PDF from the app private directory
const path = this.getUIContext().getHostContext()!.filesDir + '/test.pdf';
this.controller.loadUrl(path);
})
Button('Load Resource PDF')
.onClick(() => {
// Load a PDF from rawfile resources
this.controller.loadUrl('resource://rawfile/test.pdf');
})
Web({ src: 'resource://rawfile/test.pdf', controller: this.controller })
.domStorageAccess(true) // Recommended for PDF preview
.fileAccess(true) // Required when accessing sandbox files
.width('100%')
.height('80%')
}
}
}
This code demonstrates the standard way to switch between PDF sources under a single controller.
The initial PDF display state can be controlled precisely with URL fragments
ArkWeb supports passing the initial page number, zoom ratio, toolbar visibility, navigation pane visibility, and background color through URL fragments. This allows developers to define the initial reading state quickly without adding an extra UI control layer.
These parameters are especially useful in contract review, help-document deep linking, and branded reading interfaces. One important detail: when switching documents, do not rely on updating src. Call loadUrl() instead.
You should understand the scope of each common parameter
| Parameter | Purpose | Example |
|---|---|---|
page |
Specifies the initial page number, starting from 1 | #page=3 |
zoom |
Specifies the zoom ratio | #zoom=50 |
toolbar |
Controls top toolbar visibility | #toolbar=0 |
navpanes |
Controls side navigation visibility | #navpanes=0 |
pdfbackgroundcolor |
Sets the background color | #pdfbackgroundcolor=ffffff |
// Jump to page 3 and set the zoom ratio
this.controller.loadUrl('https://www.example.com/test.pdf#page=3&zoom=50');
// Hide the toolbar and side navigation
this.controller.loadUrl('resource://rawfile/test.pdf#toolbar=0&navpanes=0');
This code defines how the PDF should appear on first render rather than dynamically modifying Web initialization parameters.
onPdfLoadEvent makes PDF load failures traceable and actionable
onPdfLoadEvent is one of the most important enhancements in API 20+. Its callback parameters include url and result, where result = 0 typically indicates success and any non-zero value indicates failure. As a result, PDFs finally have an explicit result state.
For business logic, the value of this event goes beyond showing an error message. More importantly, it supports retries, performance monitoring, cache warming, and exception reporting.
The recommended onPdfLoadEvent pattern should update both UI and logs
import { webview } from '@kit.ArkWeb';
@Entry
@Component
struct PdfPreviewWithLoadEvent {
controller: webview.WebviewController = new webview.WebviewController();
@State loadStatus: string = 'Waiting to load...';
@State isLoadError: boolean = false;
build() {
Column() {
Text(`Load Status: ${this.loadStatus}`)
.fontColor(this.isLoadError ? '#FF4444' : '#2E7D32')
.padding(12)
Web({ src: 'https://www.example.com/test.pdf', controller: this.controller })
.domStorageAccess(true)
.onPdfLoadEvent((eventInfo: OnPdfLoadEvent) => {
// Determine whether the PDF loaded successfully based on result
if (eventInfo.result === 0) {
this.loadStatus = 'Load successful';
this.isLoadError = false;
console.info(`PDF loaded successfully: ${eventInfo.url}`);
} else {
this.loadStatus = `Load failed, error code: ${eventInfo.result}`;
this.isLoadError = true;
console.error(`PDF load failed: ${eventInfo.url}`);
}
})
.width('100%')
.height('80%')
}
}
}
This code maps the PDF load result directly to UI state.
This event is best suited for retry flows and performance instrumentation
When the network is unstable or the file is corrupted, the page should not leave users with a blank area. The standard approach is to use the callback to display an error state, record the error code, and expose a retry button. For document-center applications, you should also track load time across different document sources.
.onPdfLoadEvent((eventInfo: OnPdfLoadEvent) => {
// Record performance on success and trigger a retry strategy on failure
if (eventInfo.result === 0) {
const loadTime = Date.now() - this.startTime;
this.reportPerformance('pdf_load_time', loadTime);
} else {
this.showRetryDialog(eventInfo.url);
}
})
This code highlights the dual value of onPdfLoadEvent for both usability and operability.
onPdfScrollAtBottom makes reading completion reliable for the first time
Previously, PDFs inside Web views behaved like embedded plugins. Standard scroll listeners could not access internal scroll position, so developers had to rely on approximate signals such as onOverScroll, which introduced errors and increased maintenance costs. onPdfScrollAtBottom solves this by exposing “reached the end” as an atomic event.
This matters because many business flows do not care about the scrolling process itself. They care about whether the user actually finished reading. Typical examples include unlocking contract signing, recording read completion, and auto-loading the next document in a series.
Triggering business logic only after bottom detection is a safer interaction model
import { webview } from '@kit.ArkWeb';
@Entry
@Component
struct PdfPreviewWithScrollEvent {
controller: webview.WebviewController = new webview.WebviewController();
@State bottomReachedCount: number = 0;
@State canSign: boolean = false;
build() {
Column() {
Text(this.canSign ? 'Reading complete. You can continue.' : 'Please scroll to the bottom of the document first')
.padding(12)
Web({ src: 'https://www.example.com/contract.pdf', controller: this.controller })
.domStorageAccess(true)
.onPdfScrollAtBottom((eventInfo: OnPdfScrollEvent) => {
// Update business state after reaching the bottom
this.bottomReachedCount++;
this.canSign = true;
console.info(`PDF scrolled to bottom: ${eventInfo.url}`);
})
.width('100%')
.height('75%')
Button('Sign and Confirm')
.enabled(this.canSign) // Allow signing only after reading is complete
}
}
}
This code establishes a clear binding between “reading complete” and “signing allowed.”
This event fits ebooks, contracts, and sequential reading flows
In ebook scenarios, you can record the document as completed and show a rating prompt after the user reaches the bottom. In contract scenarios, you can unlock the signature or confirmation button. In document-stream scenarios, you can automatically load the next PDF to create a continuous reading experience.
.onPdfScrollAtBottom((eventInfo: OnPdfScrollEvent) => {
// Automatically switch to the next document
if (this.hasNextDocument()) {
const nextPdfUrl = this.getNextDocumentUrl();
this.controller.loadUrl(nextPdfUrl);
}
})
This code is useful for building a seamless reading flow based on the bottom-reached event.
A complete PDF reading workflow requires both events to work together
The best practice is not to listen to only one event in isolation. Instead, connect load status with reading completion: first confirm that the document is readable, then confirm that the user has finished reading, and finally trigger the business action. This avoids interference between error states and workflow states.
In implementation, it is recommended to maintain four states: isLoading, loadSuccess, errorMessage, and hasReachedBottom. These cover loading progress, load result, error details, and reading progress, respectively.
The combined example is closer to real product logic
Web({ src: 'https://www.example.com/test.pdf', controller: this.controller })
.domStorageAccess(true)
.onPdfLoadEvent((eventInfo: OnPdfLoadEvent) => {
// First determine whether the document is readable
this.isLoading = false;
this.loadSuccess = eventInfo.result === 0;
this.errorMessage = this.loadSuccess ? '' : `Error code: ${eventInfo.result}`;
})
.onPdfScrollAtBottom((eventInfo: OnPdfScrollEvent) => {
// Then determine whether the user has finished reading
if (this.loadSuccess) {
this.hasReachedBottom = true;
this.showToast('You have reached the end of the document');
}
})
This code demonstrates the combined pattern of “confirm successful load first, then allow reading-completion logic.”
Developers should pay attention to several ArkWeb PDF callback details
First, these event capabilities require API 20+, so you need a downgrade strategy for earlier versions. Second, src is not suitable for switching PDFs directly through state updates. Use the controller’s loadUrl() consistently instead. Third, network, sandbox, and resource sources require different permissions and access switches, so make those requirements explicit during initialization.
Fourth, onPdfScrollAtBottom is better suited for key milestone triggers than for high-frequency analytics. If you need to record multiple bottom-reached actions, implement idempotency control to avoid repeated dialogs and duplicate submissions.
FAQ
Q1: Why must I enable domStorageAccess(true) when previewing PDFs in ArkWeb?
A: The PDF preview page uses window.localStorage to persist state such as side navigation. If DOM storage is not enabled, some features may behave incorrectly or fail to preserve state.
Q2: Why does the PDF not switch as expected after I update src?
A: ArkWeb WebOptions initial src is not suitable for dynamic switching through @State. The correct approach is to keep a WebviewController instance and call loadUrl() to switch documents.
Q3: Can onPdfScrollAtBottom replace a regular onScroll event?
A: Not completely. It provides precise notification when internal PDF scrolling reaches the end, which makes it ideal for reading-completion scenarios. For standard web pages or non-PDF content, you still need regular scroll events.
[AI Readability Summary]
This article systematically explains the PDF enhancements in HarmonyOS 6.0 ArkWeb, with a focus on the two new API 20+ callbacks,
onPdfLoadEventandonPdfScrollAtBottom. It covers loading methods, parameter configuration, typical scenarios, and combined usage patterns to help developers build observable and interactive PDF preview experiences.