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.

KPdfViewerState is the single controller for one PDF viewer instance. It owns the document load pipeline, page navigation, zoom level, and all platform-integration flows. Every KPDF component — KPdfViewer, KPdfViewerToolbar, and KPdfThumbnailStrip — reads from the same state instance, so the entire UI stays in sync automatically without any extra wiring on your part.

Unidirectional data flow

KPDF follows a strict unidirectional pattern: your UI calls an action on KPdfViewerState, the state processes the request internally, and the result surfaces through one of the observable StateFlow properties. Your composables collect those flows and rebuild in response. You never write directly to the state fields.
User action


KPdfViewerState.action()


Internal processing


StateFlow emits new value


Composable recomposes

Observable properties

PropertyTypeDescription
sourceKPdfSourceThe source that is currently open or being loaded.
configKPdfViewerConfigThe active configuration for this viewer instance.
loadStateStateFlow<KPdfLoadState>Lifecycle state of the document load pipeline — Idle, Loading, Ready, or Error.
currentPageIndexStateFlow<Int>0-based index of the page currently shown.
currentZoomStateFlow<Float>Active zoom factor.
renderedPageStateFlow<KPdfRenderedPageState>Result of the most recent page render.
openDocumentStateStateFlow<KPdfOpenDocumentState>Lifecycle of the platform file picker flow.
saveStateStateFlow<KPdfSaveState>Lifecycle of an in-progress save or export operation.
externalOpenStateStateFlow<KPdfExternalOpenState>Lifecycle of an open-in-external-app operation.

Actions

Document management

ActionDescription
open(source)Open a source, cancelling any in-flight work. Defaults to the current source (retry).
retry()Retry the most recent open call.
close()Close the active document and release resources.
exportPdf()Export the current PDF as raw bytes. Returns Result<ByteArray>. Suspend function.
ActionDescription
nextPage()Advance to the next page.
previousPage()Go back to the previous page.
goToPage(index)Jump to a specific page by its 0-based index.

Zoom

ActionDescription
setZoom(zoom)Set an exact zoom factor.
zoomIn()Increase zoom by one viewer-defined step.
zoomOut()Decrease zoom by one viewer-defined step.
resetZoom()Reset zoom to the configured minimum.

Rendering

ActionDescription
renderPage(pageIndex, targetWidth, targetHeight, zoom)Render a page to a bitmap for custom UI layers. Suspend function, returns Result<KPdfPageBitmap>.

Platform integrations

ActionDescription
requestOpenFromDevice(mimeTypes)Trigger the platform file picker.
requestSave(suggestedFileName, mimeType)Initiate the platform save flow.
savePdf(suggestedFileName, mimeType)Alias for requestSave.
openInExternalApp(suggestedFileName, mimeType)Hand the current PDF to an external app.
requestOpenInExternalApp(suggestedFileName, mimeType)Explicit form of openInExternalApp.

Creating viewer state

In Compose, use rememberPdfViewerState to create and remember a state instance tied to the composition lifecycle:
@Composable
fun PdfScreen(url: String) {
    val source = remember(url) { KPdfSource.Url(url) }
    val config = remember { KPdfViewerConfig.builder().build() }

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

    KPdfViewer(
        state = viewerState,
        modifier = Modifier.fillMaxSize(),
    )
}
If you manage lifecycle yourself outside of Compose, create state through the core facade:
val sdk = KPdfFactory.create()
val viewerState = sdk.viewerState(
    source = KPdfSource.Url("https://example.com/file.pdf"),
    config = KPdfViewerConfig.builder().build(),
)

Sharing state across components

Pass the same viewerState instance to every KPDF component. All three components read and react to the same flows, so navigation, zoom, and load state stay synchronized without any extra code:
@Composable
fun FullPdfScreen(source: KPdfSource) {
    val viewerState = rememberPdfViewerState(source = source)
    var thumbnailsVisible by remember { mutableStateOf(true) }
    val scope = rememberCoroutineScope()

    Column(modifier = Modifier.fillMaxSize()) {
        // Toolbar shares the same state
        KPdfViewerToolbar(
            state = viewerState,
            isThumbnailStripVisible = thumbnailsVisible,
            onThumbnailToggle = { thumbnailsVisible = it },
            onShareClick = {
                scope.launch {
                    viewerState.exportPdf().onSuccess { bytes -> sharePdfBytes(bytes) }
                }
            },
        )

        // Main viewer surface
        KPdfViewer(
            state = viewerState,
            modifier = Modifier.weight(1f),
        )

        // Thumbnail strip shares the same state
        if (thumbnailsVisible) {
            KPdfThumbnailStrip(
                state = viewerState,
                onPageClick = { viewerState.goToPage(it) },
            )
        }
    }
}

Collecting state in your UI

Collect StateFlow properties with collectAsState() to drive your own UI elements:
@Composable
fun PageCounter(viewerState: KPdfViewerState) {
    val loadState by viewerState.loadState.collectAsState()
    val currentPage by viewerState.currentPageIndex.collectAsState()

    val pageCount = (loadState as? KPdfLoadState.Ready)?.pageCount ?: 0

    Text("Page ${currentPage + 1} of $pageCount")
}