Custom Activity with Toolbars
Use toolbars within the custom activity using PdfFragment.
/* * Copyright © 2014-2026 PSPDFKit GmbH. All rights reserved. * * The PSPDFKit Sample applications are licensed with a modified BSD license. * Please see License for details. This notice may not be removed from this file. */
package com.pspdfkit.catalog.examples.java;
import android.content.Context;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.widget.Button;import androidx.annotation.NonNull;import androidx.annotation.Nullable;import androidx.appcompat.app.AlertDialog;import androidx.appcompat.app.AppCompatActivity;import com.pspdfkit.catalog.R;import com.pspdfkit.catalog.SdkExample;import com.pspdfkit.catalog.tasks.ExtractAssetTask;import com.pspdfkit.configuration.PdfConfiguration;import com.pspdfkit.configuration.activity.PdfActivityConfiguration;import com.pspdfkit.ui.PdfFragment;import com.pspdfkit.ui.annotations.OnAnnotationCreationModeChangeListener;import com.pspdfkit.ui.annotations.OnAnnotationEditingModeChangeListener;import com.pspdfkit.ui.inspector.PropertyInspectorCoordinatorLayout;import com.pspdfkit.ui.inspector.annotation.AnnotationCreationInspectorController;import com.pspdfkit.ui.inspector.annotation.AnnotationEditingInspectorController;import com.pspdfkit.ui.inspector.annotation.DefaultAnnotationCreationInspectorController;import com.pspdfkit.ui.inspector.annotation.DefaultAnnotationEditingInspectorController;import com.pspdfkit.ui.special_mode.controller.AnnotationCreationController;import com.pspdfkit.ui.special_mode.controller.AnnotationEditingController;import com.pspdfkit.ui.special_mode.controller.TextSelectionController;import com.pspdfkit.ui.special_mode.manager.TextSelectionManager;import com.pspdfkit.ui.toolbar.AnnotationCreationToolbar;import com.pspdfkit.ui.toolbar.AnnotationEditingToolbar;import com.pspdfkit.ui.toolbar.ContextualToolbar;import com.pspdfkit.ui.toolbar.TextSelectionToolbar;import com.pspdfkit.ui.toolbar.ToolbarCoordinatorLayout;
/** * This example shows how to use {@link ContextualToolbar}s withing the custom activity that uses * {@link PdfFragment}. */public class ToolbarsInFragmentExample extends SdkExample {
public ToolbarsInFragmentExample(@NonNull Context context) { super(context, R.string.toolbarsInFragmentExampleTitle, R.string.toolbarsInFragmentExampleDescription); }
@Override public void launchExample( @NonNull final Context context, @NonNull final PdfActivityConfiguration.Builder configuration) { ExtractAssetTask.extract(WELCOME_DOC, getTitle(), context, documentFile -> { final Intent intent = new Intent(context, ToolbarsInFragmentActivity.class); intent.putExtra(ToolbarsInFragmentActivity.EXTRA_URI, Uri.fromFile(documentFile)); intent.putExtra( ToolbarsInFragmentActivity.EXTRA_CONFIGURATION, configuration.build().getConfiguration()); context.startActivity(intent); }); }
/** * This example shows how to incorporate {@link ContextualToolbar}s into the custom activity using * {@link PdfFragment} with all the animations and dragging managed by the {@link * ToolbarCoordinatorLayout}. */ public static class ToolbarsInFragmentActivity extends AppCompatActivity implements OnAnnotationCreationModeChangeListener, OnAnnotationEditingModeChangeListener, TextSelectionManager.OnTextSelectionModeChangeListener {
public static final String EXTRA_URI = "ToolbarsInFragmentActivity.DocumentUri"; public static final String EXTRA_CONFIGURATION = "ToolbarsInFragmentActivity.PdfConfiguration";
private PdfFragment fragment; private ToolbarCoordinatorLayout toolbarCoordinatorLayout; private Button annotationCreationButton;
private AnnotationCreationToolbar annotationCreationToolbar; private TextSelectionToolbar textSelectionToolbar; private AnnotationEditingToolbar annotationEditingToolbar;
private boolean annotationCreationActive = false;
private PropertyInspectorCoordinatorLayout inspectorCoordinatorLayout; private AnnotationEditingInspectorController annotationEditingInspectorController; private AnnotationCreationInspectorController annotationCreationInspectorController;
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_annotation_toolbar_fragment); setSupportActionBar(null);
toolbarCoordinatorLayout = findViewById(R.id.toolbarCoordinatorLayout);
annotationCreationToolbar = new AnnotationCreationToolbar(this); textSelectionToolbar = new TextSelectionToolbar(this); annotationEditingToolbar = new AnnotationEditingToolbar(this);
// Use this if you want to use annotation inspector with annotation creation and editing // toolbars. inspectorCoordinatorLayout = findViewById(R.id.inspectorCoordinatorLayout); annotationEditingInspectorController = new DefaultAnnotationEditingInspectorController(this, inspectorCoordinatorLayout); annotationCreationInspectorController = new DefaultAnnotationCreationInspectorController(this, inspectorCoordinatorLayout);
// The actual document Uri is provided with the launching intent. You can simply change that // inside the ToolbarsInFragmentExample class. // This is a check that the example is not accidentally launched without a document Uri. final Uri uri = getIntent().getParcelableExtra(EXTRA_URI); if (uri == null) { showNoDocumentUriDialog(); return; }
// PdfFragment configuration is provided with the launching intent. PdfConfiguration configuration = getIntent().getParcelableExtra(EXTRA_CONFIGURATION); if (configuration == null) { configuration = new PdfConfiguration.Builder().build(); }
initPdfFragment(uri, configuration); initAnnotationCreationButton(); }
private void showNoDocumentUriDialog() { new AlertDialog.Builder(this) .setTitle("Could not start example.") .setMessage("No document Uri was provided with the launching intent.") .setNegativeButton("Leave example", (dialog, which) -> dialog.dismiss()) .setOnDismissListener(dialog -> finish()) .show(); }
private void initAnnotationCreationButton() { annotationCreationButton = findViewById(R.id.openAnnotationEditing); annotationCreationButton.setOnClickListener(v -> { if (annotationCreationActive) { fragment.exitCurrentlyActiveMode(); } else { fragment.enterAnnotationCreationMode(); } });
updateButtonText(); }
private void initPdfFragment(@NonNull Uri uri, @NonNull PdfConfiguration configuration) { fragment = (PdfFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentContainer); if (fragment == null) { fragment = PdfFragment.newInstance(uri, configuration); getSupportFragmentManager() .beginTransaction() .add(R.id.fragmentContainer, fragment) .commit(); }
fragment.addOnAnnotationCreationModeChangeListener(this); fragment.addOnAnnotationEditingModeChangeListener(this); fragment.addOnTextSelectionModeChangeListener(this); }
@Override protected void onDestroy() { super.onDestroy(); fragment.removeOnAnnotationCreationModeChangeListener(this); fragment.removeOnAnnotationEditingModeChangeListener(this); fragment.removeOnTextSelectionModeChangeListener(this); }
@Override public void onEnterAnnotationCreationMode(@NonNull AnnotationCreationController controller) { // When entering the annotation creation mode we bind the creation inspector to the provided // controller. // Controller handles request for toggling annotation inspector. annotationCreationInspectorController.bindAnnotationCreationController(controller);
// When entering the annotation creation mode we bind the toolbar to the provided // controller, and // issue the coordinator layout to animate the toolbar in place. // Whenever the user presses an action, the toolbar forwards this command to the controller. // Instead of using the `AnnotationEditingToolbar` you could use a custom UI that operates // on the controller. // Same principle is used on all other toolbars. annotationCreationToolbar.bindController(controller); toolbarCoordinatorLayout.displayContextualToolbar(annotationCreationToolbar, true); annotationCreationActive = true; updateButtonText(); }
@Override public void onChangeAnnotationCreationMode(@NonNull AnnotationCreationController controller) { // Nothing to be done here, if toolbar is bound to the controller it will pick up the // changes. }
@Override public void onExitAnnotationCreationMode(@NonNull AnnotationCreationController controller) { // Once we're done with editing, unbind the controller from the toolbar, and remove it from // the // toolbar coordinator layout (with animation in this case). // Same principle is used on all other toolbars. toolbarCoordinatorLayout.removeContextualToolbar(true); annotationCreationToolbar.unbindController(); annotationCreationActive = false;
// Also unbind the annotation creation controller from the inspector controller. annotationCreationInspectorController.unbindAnnotationCreationController();
updateButtonText(); }
@Override public void onEnterAnnotationEditingMode(@NonNull AnnotationEditingController controller) { annotationEditingInspectorController.bindAnnotationEditingController(controller);
annotationEditingToolbar.bindController(controller); toolbarCoordinatorLayout.displayContextualToolbar(annotationEditingToolbar, true); }
@Override public void onChangeAnnotationEditingMode(@NonNull AnnotationEditingController controller) { // Nothing to be done here, if toolbar is bound to the controller it will pick up the // changes. }
@Override public void onExitAnnotationEditingMode(@NonNull AnnotationEditingController controller) { toolbarCoordinatorLayout.removeContextualToolbar(true); annotationEditingToolbar.unbindController();
annotationEditingInspectorController.unbindAnnotationEditingController(); }
@Override public void onEnterTextSelectionMode(@NonNull TextSelectionController controller) { textSelectionToolbar.bindController(controller); toolbarCoordinatorLayout.displayContextualToolbar(textSelectionToolbar, true); }
@Override public void onExitTextSelectionMode(@NonNull TextSelectionController controller) { toolbarCoordinatorLayout.removeContextualToolbar(true); textSelectionToolbar.unbindController(); }
private void updateButtonText() { annotationCreationButton.setText(annotationCreationActive ? R.string.close_editor : R.string.open_editor); } }}This code sample is an example that illustrates how to use our SDK. Please adapt it to your specific use case.