Jetpack Compose PDF viewer

Since Nutrient Android SDK version 8, our SDK exposes Jetpack Compose-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 composable.

Displaying a document

To display a document, use the DocumentView composable function that expects a Uri 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 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 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 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 demonstrating everything related to DocumentView and the com.pspdfkit.jetpack.compose package.