HarmonyOS 6.0 ArkWeb PDF Callbacks Explained: Load Status Tracking and Bottom Scroll Detection

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

ArkWeb PDF Preview Capability Diagram 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 regular onScroll event.
  • 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, onPdfLoadEvent and onPdfScrollAtBottom. It covers loading methods, parameter configuration, typical scenarios, and combined usage patterns to help developers build observable and interactive PDF preview experiences.