A lightweight Android PDF viewer library powered by Mozilla's PDF.js, offering seamless PDF rendering and interactive features. Supports both Jetpack Compose and Xml.
For setup see Setup
For XML examples see XML Examples
@Composable
fun SimplePdfViewer() {
val pdfState = rememberPdfState("asset://sample.pdf")
PdfViewer(
pdfState = pdfState,
modifier = Modifier
)
}@Composable
fun PdfViewerContainerColor() {
val pdfState = rememberPdfState("asset://sample.pdf")
PdfViewer(
pdfState = pdfState,
modifier = Modifier,
containerColor = Color.Transparent
)
}@Composable
fun PdfViewerDefaultOnReadyCallback() {
val pdfState = rememberPdfState("asset://sample.pdf")
PdfViewer(
pdfState = pdfState,
modifier = Modifier,
onReady = DefaultOnReadyCallback { // this: PdfViewer
// loadSource is called before this callback
}
)
}@Composable
fun PdfViewerCustomOnReadyCallback() {
val pdfState = rememberPdfState("asset://sample.pdf")
PdfViewer(
pdfState = pdfState,
modifier = Modifier,
onReady = CustomOnReadyCallback { loadSource -> // this: PdfViewer
loadSource() // Mandatory to call
}
)
}@Composable
fun PdfViewerWithContainer() {
val pdfState = rememberPdfState("asset://sample.pdf")
PdfViewerContainer(
pdfState = pdfState,
pdfViewer = {// this: PdfContainerBoxScope
PdfViewer( // pdfState is passed by PdfContainerBoxScope
modifier = Modifier,
)
}
)
}@Composable
fun PdfViewerWithToolBarAndScrollBar() {
val pdfState = rememberPdfState("asset://sample.pdf")
PdfViewerContainer(
pdfState = pdfState,
pdfViewer = {
PdfViewer(
modifier = Modifier
)
},
pdfToolBar = {
PdfToolBar(
title = "Title",
)
},
pdfScrollBar = { parentSize ->
PdfScrollBar(
parentSize = parentSize
)
},
)
}@Composable
fun ToolBarBack() {
val pdfState = rememberPdfState("asset://sample.pdf")
PdfViewerContainer(
pdfState = pdfState,
pdfViewer = {
PdfViewer(
modifier = Modifier
)
},
pdfToolBar = {
PdfToolBar(
title = "Title",
onBack = {
// called when back is clicked
},
// backIcon = { // this: PdfToolBarScope
// // or create your own back icon
// }
)
},
pdfScrollBar = { parentSize ->
PdfScrollBar(
parentSize = parentSize
)
},
)
}@Composable
fun ListeningForFindBarState() {
val pdfState = rememberPdfState("asset://sample.pdf")
val toolBarState = rememberToolBarState()
LaunchedEffect(toolBarState.isFindBarOpen) {
// Do something
}
BackHandler {
if (toolBarState.isFindBarOpen)
toolBarState.isFindBarOpen = false
}
PdfViewerContainer(
pdfState = pdfState,
pdfViewer = {
PdfViewer(
modifier = Modifier
)
},
pdfToolBar = {
PdfToolBar(
title = "Title",
toolBarState = toolBarState,
)
},
pdfScrollBar = { parentSize ->
PdfScrollBar(
parentSize = parentSize
)
},
)
}@Composable
fun ExtendedToolBar() {
val pdfState = rememberPdfState("asset://sample.pdf")
PdfViewerContainer(
pdfState = pdfState,
pdfViewer = {
PdfViewer(
modifier = Modifier
)
},
pdfToolBar = {
PdfToolBar(
title = "Title",
dropDownMenu = { onDismiss, defaultMenus ->
ExtendedTooBarMenus(
onDismiss = onDismiss,
defaultMenus = defaultMenus
)
}
)
},
pdfScrollBar = { parentSize ->
PdfScrollBar(
parentSize = parentSize
)
},
)
}
@Composable
private fun ExtendedTooBarMenus(
onDismiss: () -> Unit,
defaultMenus: @Composable (filtered: List<PdfToolBarMenuItem>) -> Unit
) {
DropdownMenuItem(
text = { Text(text = "Extended Menu") },
onClick = {
// Do something
onDismiss()
}
)
defaultMenus(PdfToolBarMenuItem.entries)
// or defaultMenus(PdfToolBarMenuItem.entries.filter { it != PdfToolBarMenuItem.CUSTOM_PAGE_ARRANGEMENT })
}@Composable
fun Colors() {
val pdfState = rememberPdfState("asset://sample.pdf")
PdfViewerContainer(
pdfState = pdfState,
pdfViewer = {
PdfViewer(
modifier = Modifier,
containerColor = Color.Red
)
},
pdfToolBar = {
PdfToolBar(
title = "Title",
contentColor = Color.Blue,
)
},
pdfScrollBar = { parentSize ->
PdfScrollBar(
parentSize = parentSize,
contentColor = Color.Blue,
handleColor = Color.Green
)
},
)
}@Composable
fun CustomizeScrollBar() {
val pdfState = rememberPdfState("asset://sample.pdf")
PdfViewerContainer(
pdfState = pdfState,
pdfViewer = {
PdfViewer(
modifier = Modifier,
)
},
pdfToolBar = {
PdfToolBar(
title = "Title",
)
},
pdfScrollBar = { parentSize ->
PdfScrollBar(
parentSize = parentSize,
useVerticalScrollBarForHorizontalMode = true,
interactiveScrolling = true,
)
},
)
}@Composable
fun LoadingIndicator() {
val pdfState = rememberPdfState("asset://sample.pdf")
PdfViewerContainer(
pdfState = pdfState,
pdfViewer = {
PdfViewer(
modifier = Modifier,
)
},
loadingIndicator = {
Column(
Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.background),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
CircularProgressIndicator()
Text(text = "Loading...")
}
},
)
}@Composable
fun PdfViewerFactoryCallback() {
val pdfState = rememberPdfState("asset://sample.pdf")
PdfViewer(
pdfState = pdfState,
modifier = Modifier,
factory = { context ->
PdfViewer(context) // return PdfViewer instance.
}
)
}Use factory for create PdfViewer instance and use onCreateViewer for configuring
@Composable
fun PdfViewerOnCreateViewerCallback() {
val pdfState = rememberPdfState("asset://sample.pdf")
PdfViewer(
pdfState = pdfState,
modifier = Modifier,
onCreateViewer = { // this: PdfViewer
// You can add listener with extension like
addListener(onPageLoadFailed = {
})
// or
addListener(object: PdfListener {
// implement required methods
})
}
)
}Note
For Download listener see implementation in PdfViewerActivity.kt
- source: String
- pdfViewer: PdfViewer?
- loadingState: PdfLoadingState
- pagesCount: Int
- currentPage: Int
- currentScale: Float
- properties: PdfDocumentProperties?
- passwordRequired: Boolean
- scrollState: ScrollState
- matchState: MatchState
- scrollMode: PdfViewer.PageScrollMode
- spreadMode: PdfViewer.PageSpreadMode
- rotation: PdfViewer.PageRotation
- scaleLimit: ScaleLimit
- actualScaleLimit: ActualScaleLimit
- snapPage: Boolean
- singlePageArrangement: Boolean
- alignMode: PdfViewer.PageAlignMode
- scrollSpeedLimit