Jetpack Compose PDF viewer

Since Nutrient Android SDK version 8, our SDK exposes Jetpack Compose(opens in a new tab)-specific APIs out of the box, enabling PDF viewing and editing. This makes dealing with Nutrient in a Jetpack Compose app easier, and it doesn’t require you to wrap PdfFragment yourself if you want to go the Compose route.

The main entry point is the DocumentView composable. DocumentView wraps the functionality of PdfUiFragment using the AndroidView(opens in a new tab) composable.

Displaying a document

To display a document, use the DocumentView composable function that expects a Uri(opens in a new tab) parameter:

setContent {
Surface {
val documentUri = remember { getDocumentUri() }
DocumentView(
documentUri = documentUri,
modifier = Modifier
.height(100.dp)
.padding(16.dp)
)
}
}

Displaying an image

To display an image, use the ImageDocumentView composable function that expects a Uri(opens in a new tab) parameter:

setContent {
Surface {
val imageUri = remember { getDocumentUri() }
ImageDocumentView(
imageUri = imageUri,
modifier = Modifier
.height(100.dp)
.padding(16.dp)
)
}
}

Advanced use

The DocumentView and ImageDocumentView composables both have the expected Modifier(opens in a new tab) parameter, which allows you to control how these composables will be displayed inside your layout. You can also provide a DocumentState object, which is a wrapper that allows you to modify the PdfActivityConfiguration used to display the document. It also exposes operations for verifying and updating the current page of the displayed document.

The correct way of instantiating a DocumentState is via the rememberDocumentState method. Here’s how to use the DocumentView composable after hoisting the DocumentState to control the UserInterfaceViewMode, and how to ensure the DocumentView only recomposes when another property changes:

setContent {
Surface {
var hideInterfaceElements by remember { mutableStateOf(false) }
// Configuration to hide the interface.
val pdfActivityConfiguration = remember(hideInterfaceElements) {
val userInterfaceViewMode =
if (hideInterfaceElements) UserInterfaceViewMode.USER_INTERFACE_VIEW_MODE_HIDDEN
else UserInterfaceViewMode.USER_INTERFACE_VIEW_MODE_AUTOMATIC
PdfActivityConfiguration
.Builder(this)
.setUserInterfaceViewMode(userInterfaceViewMode)
.build()
}
val documentState = rememberDocumentState(documentUri, pdfActivityConfiguration)
DocumentView(
documentState = documentState,
modifier = Modifier
.height(100.dp)
.padding(16.dp),
documentManager = getDefaultDocumentManager()
)
}
}

In addition to the Uri(opens in a new tab) parameter, you can use DocumentView and ImageDocumentView composables with DataProvider as well. Below is an example of DocumentView using a resource from the assets folder via AssetDataProvider:

val dataProvider: DataProvider by remember { mutableStateOf(AssetDataProvider("demo.pdf")) }
val documentState = rememberDocumentState(dataProvider, pdfActivityConfiguration)
DocumentView(
documentState,
modifier = Modifier.fillMaxSize()
)

Interacting with DocumentView

To make interactions easier, DocumentView provides DocumentManager, which provides all the lifecycle and annotation callbacks from the Nutrient SDK. Along with this, to perform any action, DocumentConnection is provided in documentState.

Learn more about DocumentManager and DocumentConnection here.

File type support

  • PDF
  • PNG, JPEG, JPG, TIFF, TIF

Exploring further

We have a dedicated GitHub public repository(opens in a new tab) demonstrating everything related to DocumentView and the com.pspdfkit.jetpack.compose package.