KmpPdfViewer
All-in-one PDF viewer screen — recommended composable entry.
KmpPdfViewer(...) drops a complete PDF screen into your Compose hierarchy: topbar (Minimal Mono on Android, Classic iOS Native on iOS), inline search-bar morph, share & save actions, hyperlink launcher, page indicator chip, gesture-driven zoom + pan. Every piece of state — searchOpen, searchQuery, activeMatchIndex, share / save bindings — is owned by the library, not the host.
The host configures what the viewer can do (via the visibility toggles below) and what happens on back (via onBack). Nothing else is required:
KmpPdfViewer(
source = PdfSource.Remote("https://example.com/invoice.pdf"),
title = "Invoice",
onBack = { navController.popBackStack() },
)Three overloads cover every realistic input: a PdfSource (recommended — covers remote URLs, local files, content URIs, bundled assets, raw bytes and PdfKmp documents through one sealed type), a PdfDocument built through the PdfKmp DSL, or a raw ByteArray. Async sources render an inline progress indicator while loading and an error message on failure — back navigation still works in both states.
Need to launch a viewer from outside a @Composable scope — say from a click handler or LaunchedEffect? Use the imperative counterpart KmpPdfLauncher.open instead. It hosts this same composable inside a platform-native shell (Activity on Android, UIViewController on iOS).
Need finer control (custom topbar, custom share, FAB placement, multi-action overlays)? Drop down to the lower-level public composables: PdfViewer, PdfViewerTopBar, PdfSearchBar, rememberPdfShareAction, rememberPdfSaveAction, rememberPdfUrlLauncher, and searchPdfText. KmpPdfViewer is the opinionated default; the building blocks remain available for advanced layouts.
Parameters
PDF payload. PdfSource.of(document) keeps text selection + hyperlinks alive; async variants stream bytes from the platform's native loader.
applied to the outer Column.
shown in the topbar's centered title (Classic iOS) / bold first line (Minimal Mono).
user-visible filename surfaced to the share sheet and the "Saved to Downloads" entry. Must include .pdf.
callback wired to the back chip / chevron. null removes the back affordance entirely.
iOS-only previous-screen label rendered next to the chevron (e.g. "Files"). Ignored on Android.
how the topbar title behaves when it is too long to fit. PdfTopBarTitleOverflow.Ellipsis (default) truncates it with …; PdfTopBarTitleOverflow.Marquee scrolls it horizontally. The back affordance and the share / search / download icons keep their size either way — only the title yields.
master switch for the entire chrome (topbar + search bar). false hides both unconditionally — yields a "poor viewer" surface that is just pages, indicator, and gestures. When false, showBack, showSearch, showShare, showDownload all become no-ops because there is no bar to surface them on. Host apps that hide the topbar typically wire their own back navigation and share / download affordances via the platform's system UI.
hide / show the search affordance. Auto- suppressed when the source carries no text runs.
hide / show the share affordance.
hide / show the print affordance. false by default — printing is opt-in. When true the topbar surfaces a print button that hands the bytes to the platform print pipeline (PrintManager on Android, UIPrintInteractionController on iOS, java.awt.print.PrinterJob on Desktop).
hide / show the download affordance.
render every page bitmap colour-inverted (white page → near-black, black text → white) for a dark-mode reading surface. false by default. The inversion happens on the rasterised preview only — the encoded PDF and the bytes handed to share / save / print are untouched. Pair it with a dark pageBackgroundColor / backgroundColor for a seamless look.
hide / show the bottom-centre page chip.
master switch for pinch + double-tap zoom.
independent toggle for the double-tap shortcut.
toggles the invisible selectable text overlay. Only effective on documents loaded from a PdfDocument.
toggles the invisible clickable layer that opens hyperlink annotations in the system browser. Same PdfDocument-only caveat as textSelectable.
colour painted behind the page bitmaps. Defaults to the active Material 3 surface tone.
colour painted behind each individual page (visible while it's still rasterising).
padding around the androidx.compose.foundation.lazy.LazyColumn content. Defaults to zero for a fully edge-to-edge layout.
vertical gap between page previews.
baseline scaling factor applied during rasterisation.
upper bound for the pinch gesture.
controls how far ahead and behind the visible page the renderer keeps rasterised bitmaps. See PdfPageCacheStrategy for the trade-offs; defaults to PdfPageCacheStrategy.Auto which picks a window based on available RAM and never crashes.
surfaces a highlight-annotation toggle in the topbar. false by default — annotation tools are opt-in. When the toggle is on, dragging on a page paints a translucent yellow highlight and tapping an existing highlight deletes it. Overlay only: highlights live in viewer state and are never written into the PDF bytes — share / save / print get the original document (see PdfViewerAnnotation).
highlights to restore into the viewer on first composition (e.g. a list previously persisted by your app via onAnnotationsChanged). The viewer owns the mutable copy from then on.
invoked with the full annotation list every time the user adds or removes a highlight, so the host can persist them. null (the default) drops the changes — annotations then live only for the composition's lifetime.
how pages are arranged: PdfPageLayout.Single (default — continuous one-per-row scroll) or PdfPageLayout.TwoPageBook (side-by-side book spreads, cover alone, best on Desktop / tablet). There is no topbar toggle — this is a parameter-only choice; the host flips it.
unlocks an encrypted PDF. null (default) for an unencrypted document. With a missing / wrong password the viewer shows an inline "password protected" message instead of crashing and fires onDocumentError. Desktop opens it with the right password; iOS unlocks via PDFKit (pending macOS verification); Android cannot open encrypted PDFs at all (PdfRenderer has no password API) so the error is terminal there.
invoked when the document can't be opened — see PdfViewerError. The inline message is shown regardless; this lets the host react (e.g. re-prompt for a password). null by default.
Annotation export on save: when showAnnotationTools is on, there is at least one highlight, and the platform can write annotations (Desktop via PdfBox — see pdfViewerSupportsAnnotationExport), the existing download / save action writes the highlights INTO the saved PDF (real Highlight annotations, visible in any reader) instead of the originals. Share / print still export the untouched original, and on Android / iOS (no writable PDF API) save also keeps exporting the original — highlights stay overlay-only there.
PdfDocument-flavoured overload — wraps the document in a PdfSource.Document and forwards. Recommended entry point when the PDF was authored through the PdfKmp DSL because text selection and hyperlinks light up automatically.
Raw-bytes overload — for payloads that came from disk, the network, an ACTION_OPEN_DOCUMENT picker, or any other source. Text selection + hyperlink layers are inert because the bytes carry no position metadata; everything else (zoom, share, save, page indicator) works exactly the same.
Deprecated
Use KmpPdfViewer(source = PdfSource.auto(uri), …) — strings hide what transport is being used and can't carry headers / timeouts.
Replace with
import com.conamobile.pdfkmp.viewer.PdfSource
KmpPdfViewer(source = PdfSource.auto(uri), modifier = modifier, title = title, fileName = fileName, onBack = onBack, backLabel = backLabel, titleOverflow = titleOverflow, showTopBar = showTopBar, showBack = showBack, showSearch = showSearch, showShare = showShare, showPrint = showPrint, showDownload = showDownload, invertColors = invertColors, showPageIndicator = showPageIndicator, zoomEnabled = zoomEnabled, doubleTapToZoom = doubleTapToZoom, showZoomControls = showZoomControls, textSelectable = textSelectable, hyperlinksEnabled = hyperlinksEnabled, backgroundColor = backgroundColor, pageBackgroundColor = pageBackgroundColor, contentPadding = contentPadding, pageSpacing = pageSpacing, renderDensity = renderDensity, maxZoom = maxZoom, cacheStrategy = cacheStrategy)String-URI overload, deprecated in favour of PdfSource.auto.
The string form hid which transport was being used and offered no place to attach per-shape configuration (HTTP headers, timeouts, etc.). Migrate to an explicit PdfSource variant — call PdfSource.auto if you genuinely don't know the scheme at call site, or pick a constructor directly when you do.