Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mahmoud-b28887f9.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

This guide walks you through the shortest path to a working PDF viewer. By the end you will have a composable that loads a PDF from any source, renders pages with pinch-to-zoom and swipe navigation, and handles its own lifecycle cleanup.
1

Add the dependencies

Add both KPDF modules to your shared module’s build.gradle.kts:
implementation("com.mahmoud.kpdf:kpdf-core:1.0.0")
implementation("com.mahmoud.kpdf:kpdf-compose:1.0.0")
kpdf-core provides the PDF engine and state APIs. kpdf-compose provides the Compose viewer components and the platform save/open integrations. You need both for a full viewer.See Installation for full Gradle setup details and Groovy DSL equivalents.
2

Create a KPdfSource

Create a KPdfSource that tells the SDK where your PDF comes from. KPDF supports URLs, raw bytes, and Base64 strings:
// Load from a remote URL
val source = KPdfSource.Url("https://example.com/document.pdf")

// Load from bytes you already have
val source = KPdfSource.Bytes(pdfBytes)

// Load from a Base64 string or data URL
val source = KPdfSource.Base64(base64String)
For authenticated remote PDFs, pass request headers:
val source = KPdfSource.Url(
    url = "https://example.com/secure.pdf",
    headers = mapOf("Authorization" to "Bearer token")
)
3

Call rememberPdfViewerState

Inside your composable, call rememberPdfViewerState to create and remember the viewer state. Wrap source in remember and build KPdfViewerConfig inside remember so neither is reconstructed on every recomposition:
val stableSource = remember(source) { source }
val viewerConfig = remember {
    KPdfViewerConfig.builder()
        .enableSwipe(true)
        .ramCacheSize(6)
        .diskCacheSize(24)
        .preloadPageCount(2)
        .build()
}

val viewerState = rememberPdfViewerState(
    source = stableSource,
    config = viewerConfig,
)
Keep source and config stable with remember. If you rebuild KPdfViewerConfig inline on every recomposition, rememberPdfViewerState recreates the viewer state and transient flows such as openDocumentState reset back to Idle.
4

Add KPdfViewer to your layout

Pass the viewer state to KPdfViewer to render the PDF surface:
KPdfViewer(
    state = viewerState,
    modifier = Modifier.fillMaxSize(),
)
KPdfViewer reads the active page and zoom level from KPdfViewerState and handles swipe navigation and pinch-to-zoom automatically.

Complete minimal example

Here is the full composable from the steps above assembled together:
@Composable
fun PdfScreen(source: KPdfSource) {
    val stableSource = remember(source) { source }
    val viewerConfig = remember {
        KPdfViewerConfig.builder()
            .enableSwipe(true)
            .ramCacheSize(6)
            .diskCacheSize(24)
            .preloadPageCount(2)
            .build()
    }

    val viewerState = rememberPdfViewerState(
        source = stableSource,
        config = viewerConfig,
    )

    KPdfViewer(state = viewerState)
}
Pass any KPdfSource to PdfScreen and the viewer handles loading, rendering, caching, and cleanup when the composable leaves the composition.

Next steps

Once the basic viewer is working, you can extend it with connected views and platform flows:
  • Add KPdfViewerToolbar and KPdfThumbnailStrip using the same viewerState — no extra wiring required.
  • Call viewerState.requestSave() to let users save the current PDF to their device.
  • Call viewerState.requestOpenFromDevice() to let users pick a local PDF.
  • Call viewerState.openInExternalApp() to hand the PDF to another installed app.
  • Use viewerState.exportPdf() to get raw bytes and feed them into your own share flow.