Move or Copy PDF Pages on Android

PSPDFKit for Android lets you move and copy the pages of a document using the Processor API or the Document Editor API.

Using the Processor API

To move pages via the PdfProcessor API, load your document and then configure the parameters for page moving on a PdfProcessorTask instance. The Processor API is a great choice if you want to build an automated document processing operation:

// Create a `PdfProcessorTask` in which to store the operation.
val task = PdfProcessorTask.empty()
// Move pages to the end of the document.
task.movePages(setOf(1, 5, 6), document.pageCount)

// Process to an output document.
val outputFile = File(context.filesDir, "outputDocument.pdf")
PdfProcessor.processDocument(task, outputFile)
// Create a `PdfProcessorTask` in which to store the operation.
final PdfProcessorTask task = PdfProcessorTask.empty();
// Move pages to the end of the document.
task.movePages(new HashSet<>(Arrays.asList(1, 5, 6)), document.getPageCount());
// Process to an output document.
final File outputFile = new File(context.getFilesDir(), "outputDocument.pdf");
PdfProcessor.processDocument(task, outputFile);

To copy the page instead of moving it, replace the movePages call with an addNewPage call that’s configured to take a source page from the same document:

val task = PdfProcessorTask.empty()
// Copy the first page to the end of the document.
task.addNewPage(NewPage.fromPage(document, 0).build(), document.pageCount)
val outputFile = File(context.filesDir, "outputDocument.pdf")
PdfProcessor.processDocument(task, outputFile)
final PdfProcessorTask task = PdfProcessorTask.empty();
// Copy the first page to the end of the document.
task.addNewPage(NewPage.fromPage(document, 0).build(), document.getPageCount());
final File outputFile = new File(context.getFilesDir(), "outputDocument.pdf");
PdfProcessor.processDocument(task, outputFile);

Using the Document Editor API

Pages can also be moved and copied using the Document Editor API. The Document Editor API is particularly useful if you want to build a general-purpose UI for manipulating pages, as it provides helpers that make building a document editing UI easy.

Here’s how you can use the Document Editor API to move the current page of a displayed document:

// Instance method on a `PdfActivity` subclass.
fun movePages() {
    // Use the [`PdfDocumentEditorFactory`][] to create a `PdfDocumentEditor`.
    val documentEditor = PdfDocumentEditorFactory.createForDocument(document)

    // Set up the output file location.
    val outputFile = File(filesDir, "outputDocument.pdf")

    // Move the current page.
    val pagesToMove = setOf(pageIndex);

    // Make sure `disposable` is managed by the activity and destroyed correctly
    // when the activity is destroyed.
    val disposable: Disposable = documentEditor.movePages(pagesToMove, document.pageCount)
        .flatMapCompletable { documentEditor.saveDocument(context, outputFile.outputStream(), null) }
        // Use `subscribeOn` to put `saveDocument` on a background thread, as it can be slow.
        .subscribeOn(Schedulers.io())
        // Make sure the resulting document rendering goes back on the main thread.
        .observeOn(AndroidSchedulers.mainThread())
        // You can display the saved document in a new activity with the following action on `subscribe`.
        .subscribe { showDocument(context, Uri.fromFile(outputFile), null) }
}
// Instance method on a `PdfActivity` subclass.
public void movePages() {
    // Use the [`PdfDocumentEditorFactory`][] to create a `PdfDocumentEditor`.
    final PdfDocumentEditor documentEditor =
        PdfDocumentEditorFactory.createForDocument(document);

    // Set up the output file location.
    final File outputFile = new File(getFilesDir(), "outputDocument.pdf");

    // Move the current page.
    final HashSet<Integer> pagesToMove = new HashSet<>(Arrays.asList(getPageIndex()));

    // Make sure `disposable` is managed by the activity and destroyed correctly
    // when the activity is destroyed.
    final Disposable disposable = documentEditor.movePages(pagesToMove, document.getPageCount())
        .flatMapCompletable(saved -> documentEditor.saveDocument(context, new FileOutputStream(outputFile), null))
        // Use `subscribeOn` to put `saveDocument` on a background thread, as it can be slow.
        .subscribeOn(Schedulers.io())
        // Make sure the resulting document rendering goes back on the main thread.
        .observeOn(AndroidSchedulers.mainThread())
        // You can display the saved document in a new activity with the following action on `subscribe`.
        .subscribe( () -> { PdfActivity.showDocument(context,
            Uri.fromFile(outputFile), null);
        });
}

ℹ️ Note: Destination page indexes are specified differently between corresponding methods on the Processor and Document Editor APIs. This is because the Document Editor was designed to be easily connected to UI components and to match the behavior of built-in cell reordering. The Processor determines destination indexes before adjusting for any removed pages, while the Document Editor determines destination indexes after applying any removals.

Similar to how it works with the Processor API, you can use the Document Editor API to replace the movePages call with addPages to create a copy:

// Copy the first page.
val page = NewPage.fromPage(document, 0).build()
// Paste it to the end of the document and repeat the same process to save and display it.
documentEditor.addPage(document.pageCount, page)
    .flatMapCompletable { ...
// Copy the first page.
final NewPage page = NewPage.fromPage(document, 0).build();
// Paste it to the end of the document and repeat the same process to save and display it.
documentEditor.addPage(document.getPageCount(), page)
    .flatMapCompletable( ...

Using the Built-In UI

PSPDFKit for Android comes with a prebuilt user interface for document editing that includes an option to move and copy pages. To learn more, check out the Document Editor UI overview.