Skip to content
ComPDF
Guides

UI Customization

In addition to the core feature modules, the ComPDF SDK also provides the ComPDFKit_Tools module. This module includes a complete set of built-in UI components and interaction logic, enabling rapid integration on top of the core capabilities while supporting flexible extension and customization.

In addition, we provide a sample application PDFViewer, which demonstrates the integration and usage of ComPDFKit_Tools for developers’ reference.

This chapter introduces ComPDFKit_Tools from the following aspects:

  1. Overview: Description of module features and UI examples
  2. Integration: How to quickly integrate and use ComPDFKit_Tools
  3. Customization: How to customize UI and functionality

Overview

The ComPDFKit_Tools module integrates common PDF viewing and editing capabilities, including but not limited to:

  • Viewer
  • Annotations
  • Forms
  • Content Editor
  • Page Editor
  • Digital Signatures
  • Security & Watermark

By using CPDFDocumentActivity or CPDFDocumentFragment, you can quickly launch a complete PDF document interface in your project. UI behavior and functional modules can be controlled through configuration files; for deeper customization, you can also directly use the ComPDFKit_Tools module source code for secondary development.

SDK Integration

The SDK supports multiple integration methods. You can choose an appropriate solution based on your project requirements.

Version & Compatibility (Recommended)

  • Keep consistent with core modules: the compdfkit-tools version must match compdfkit and compdfkit-ui.
  • Android version: please select appropriate minSdk / compileSdk / targetSdk and AGP versions according to the SDK release notes.
  • R8 / ProGuard: if code obfuscation is enabled, please refer to the obfuscation rules provided with the SDK.

Gradle Integration

  1. Open the "settings.gradle" file in the project root directory, then add the mavenCentral repository:
diff
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
+       mavenCentral()
    }
}
  1. Open the "build.gradle" file in the application module directory:
Gradle

Edit it and add the ComPDFKit_Tools module dependency:

groovy
def compdfkitVersion = "2.6.0" // Keep consistent with compdfkit / compdfkit-ui versions

dependencies {
  implementation "com.compdf:compdfkit-tools:$compdfkitVersion"
  // Or depend on the core and UI modules separately (versions must be consistent):
  // implementation "com.compdf:compdfkit:$compdfkitVersion"
  // implementation "com.compdf:compdfkit-ui:$compdfkitVersion"
}

Manual Integration

  1. Copy "ComPDFKit-Tools.aar" into the "libs" directory of the app module.
AAR folder
  1. Add the following code to the "build.gradle" file under the app directory:
groovy
...
dependencies {
  /* ComPDFKit SDK */
  implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
  ...
}
...

Please make sure to also manually integrate ComPDFKit.aar and ComPDFKit-UI.aar as described in Section 2.5.2 to ensure proper operation.

Source Code Integration

You can obtain the ComPDFKit_Tools module source code from the SDK package or the GitHub sample project.

  1. Download or extract the SDK source code
  2. In Android Studio, import the module via File → New → Import Module
Import Module
  1. Add the following in app/build.gradle:
groovy
dependencies {
    implementation project(path: ':ComPDFKit_Tools')
}

Usage

After completing module integration, you can launch the document interface via CPDFDocumentActivity or CPDFDocumentFragment. UI and feature configurations are controlled via CPDFConfiguration. The default configuration file is tools_default_configuration.json.

Tip (Android 10 / 11+ Storage Access)

  • It is recommended to open and save documents using Uri (SAF / MediaStore). Direct file paths may be restricted by Scoped Storage on newer Android versions.
  • tools_default_configuration.json is packaged by default in the Tools module assets directory and can be used directly or copied into the app assets directory to override the default configuration.

Minimum example (open via Uri, Activity mode):

java
Intent intent = new Intent(context, CPDFDocumentActivity.class);
intent.setData(uri); // Uri returned by SAF picker
intent.putExtra(CPDFDocumentActivity.EXTRA_FILE_PASSWORD, password); // Optional
CPDFConfiguration configuration = CPDFConfigurationUtils.normalConfig(context, "tools_default_configuration.json");
intent.putExtra(CPDFDocumentActivity.EXTRA_CONFIGURATION, configuration);
intent.putExtra(CPDFDocumentActivity.EXTRA_PAGE_INDEX, 0);
context.startActivity(intent);
val intent = Intent(context, CPDFDocumentActivity::class.java).apply {
    data = uri // Uri returned by SAF picker
    putExtra(CPDFDocumentActivity.EXTRA_FILE_PASSWORD, password) // Optional
    val configuration = CPDFConfigurationUtils.normalConfig(context, "tools_default_configuration.json")
    putExtra(CPDFDocumentActivity.EXTRA_CONFIGURATION, configuration)
    putExtra(CPDFDocumentActivity.EXTRA_PAGE_INDEX, 0)
}
context.startActivity(intent)
  1. Open a PDF file via Uri path
java
// CPDFDocumentActivity
Intent intent = new Intent(context, CPDFDocumentActivity.class);
intent.setData(uri);
// Password is optional
intent.putExtra(CPDFDocumentActivity.EXTRA_FILE_PASSWORD, password);
// tools_default_configuration.json is included in the Tools module assets directory
CPDFConfiguration configuration = CPDFConfigurationUtils.normalConfig(context, "tools_default_configuration.json");
intent.putExtra(CPDFDocumentActivity.EXTRA_CONFIGURATION, configuration);
// Default page index when opening
intent.putExtra(CPDFDocumentActivity.EXTRA_PAGE_INDEX, 0);
context.startActivity(intent);

// CPDFDocumentFragment
CPDFConfiguration configuration = CPDFConfigurationUtils.normalConfig(context, "tools_default_configuration.json");
CPDFDocumentFragment documentFragment = CPDFDocumentFragment.newInstance(uri, "password", configuration);
getSupportFragmentManager()
  .beginTransaction()
  .replace(R.id.fragment_container_view, documentFragment, "documentFragment")
  .commit();
kotlin
// CPDFDocumentActivity
val intent = Intent(context, CPDFDocumentActivity::class.java).apply {
    data = uri // Uri returned by SAF picker
    putExtra(CPDFDocumentActivity.EXTRA_FILE_PASSWORD, password) // Password is optional
    // tools_default_configuration.json is included in the Tools module assets directory
    val configuration = CPDFConfigurationUtils.normalConfig(context, "tools_default_configuration.json")
    putExtra(CPDFDocumentActivity.EXTRA_CONFIGURATION, configuration)
    putExtra(CPDFDocumentActivity.EXTRA_PAGE_INDEX, 0) // Default page index when opening
}
context.startActivity(intent)

// CPDFDocumentFragment
val configuration = CPDFConfigurationUtils.normalConfig(context, "tools_default_configuration.json")
val documentFragment = CPDFDocumentFragment.newInstance(uri, "password", configuration)
supportFragmentManager
    .beginTransaction()
    .replace(R.id.fragment_container_view, documentFragment, "documentFragment")
    .commit()
  1. Open a PDF file via file path (note Scoped Storage restrictions)
java
// CPDFDocumentActivity
Intent intent = new Intent(context, CPDFDocumentActivity.class);
intent.putExtra(CPDFDocumentActivity.EXTRA_FILE_PATH, filePath);
// Password is optional
intent.putExtra(CPDFDocumentActivity.EXTRA_FILE_PASSWORD, password);
// tools_default_configuration.json is included in the Tools module assets directory
CPDFConfiguration configuration = CPDFConfigurationUtils.normalConfig(context, "tools_default_configuration.json");
intent.putExtra(CPDFDocumentActivity.EXTRA_CONFIGURATION, configuration);
// Default page index when opening
intent.putExtra(CPDFDocumentActivity.EXTRA_PAGE_INDEX, 0);
context.startActivity(intent);

// CPDFDocumentFragment
CPDFConfiguration configuration = CPDFConfigurationUtils.normalConfig(context, "tools_default_configuration.json");
CPDFDocumentFragment documentFragment = CPDFDocumentFragment.newInstance(filePath, password, configuration);
getSupportFragmentManager()
  .beginTransaction()
  .replace(R.id.fragment_container_view, documentFragment, "documentFragment")
  .commit();
kotlin
// CPDFDocumentActivity
val intent = Intent(context, CPDFDocumentActivity::class.java).apply {
    putExtra(CPDFDocumentActivity.EXTRA_FILE_PATH, filePath) // File path
    putExtra(CPDFDocumentActivity.EXTRA_FILE_PASSWORD, password) // Password is optional
    // tools_default_configuration.json is included in the Tools module assets directory
    val configuration = CPDFConfigurationUtils.normalConfig(context, "tools_default_configuration.json")
    putExtra(CPDFDocumentActivity.EXTRA_CONFIGURATION, configuration)
    putExtra(CPDFDocumentActivity.EXTRA_PAGE_INDEX, 0) // Default page index when opening
}
context.startActivity(intent)

// CPDFDocumentFragment
val configuration = CPDFConfigurationUtils.normalConfig(context, "tools_default_configuration.json")
val documentFragment = CPDFDocumentFragment.newInstance(filePath, password, configuration)
supportFragmentManager
    .beginTransaction()
    .replace(R.id.fragment_container_view, documentFragment, "documentFragment")
    .commit()

After running, the result is shown below:

2.6.2_3

Customization

This section describes how to customize the functionality and UI of ComPDFKit_Tools through configuration files, including:

  • Enabling / disabling feature modules
  • Setting default attributes
  • Customizing toolbars and menus
  • Customizing context menus
  • Adding event callbacks

All examples are based on tools_default_configuration.json. You can copy this file into your project’s assets directory for modification and testing.

Custom Feature Modules

You can configure the default mode, available modes, and UI display behavior via modeConfig.

  • Set the default mode (snippet example)
json
// tools_default_configuration.json
{
  "modeConfig": {
    // viewer, annotations, contentEditor, forms, signatures
    "initialViewMode": "viewer"
  }
}
  • Set the list of enabled modes (snippet example)
json
// tools_default_configuration.json
{
  "modeConfig": {
    "initialViewMode": "viewer",
    "availableViewModes": [
      "viewer",
      "annotations",
      "contentEditor",
      "forms",
      "signatures"
    ]
  }
}
  • UI display mode (snippet example)
json
// tools_default_configuration.json
{
  "modeConfig": {
    // automatic : Automatic mode. Tap the PDF page to toggle fullscreen
    // always : Always show top and bottom toolbars, no auto hiding
    // never: Hide top and bottom toolbars and never show them
    "uiVisibilityMode": "automatic"
  }
}

Use it when creating a CPDFDocumentFragment instance:

java
CPDFConfiguration configuration = CPDFConfigurationUtils.normalConfig(context, "tools_default_configuration.json");
CPDFDocumentFragment documentFragment = CPDFDocumentFragment.newInstance(uri, "password", configuration);

The usage of CPDFDocumentActivity is the same. Please refer to Section 2.6.3.

Set Default Attributes

You can uniformly set default styles for annotations, content editing, and forms in the configuration file, such as colors, transparency, and fonts.

json
// tools_default_configuration.json
{ 
  "annotationsConfig": {
    "initAttribute": {
      "note": {                        // Note annotation attributes
        "color": "#1460F3",
        "alpha": 255                  // Value range: 0–255
      },
      "highlight": {                  // Highlight annotation attributes
        "color": "#1460F3",
        "alpha": 77
      },
      "freeText": {
        "fontColor": "#000000",
        "fontColorAlpha": 255,
        "fontSize": 30,
        "alignment": "left",
        "familyName": "Helvetica",    // Font family name, see the Font Management section for details
        "styleName": "Regular"        // Font style
      }
    }
  }
}

Only part of the configuration is shown as an example. For the complete content, please refer to tools_default_configuration.json

  • Set form attributes
json
// tools_default_configuration.json
{ 
  "formsConfig": {
    "initAttribute": {							
      "textField": {                        // Text field form attributes
        "fillColor": "#DDE9FF",
        "borderColor": "#1460F3",
        "borderWidth": 2,
        "fontColor": "#000000",
        "fontSize": 20,
        "alignment": "left",
        "multiline": true,
        "familyName": "Helvetica",
        "styleName": "Regular"
      },
      "checkBox": {                         // Check box attributes
        "fillColor": "#DDE9FF",
        "borderColor": "#1460F3",
        "borderWidth": 2,
        "checkedColor": "#43474D",
        "isChecked": false,
        "checkedStyle": "check"             // check, circle, cross, diamond, square, star
      },
      "listBox": {                          // List box attributes
        "fillColor": "#DDE9FF",
        "borderColor": "#1460F3",
        "borderWidth": 2,
        "fontColor": "#000000",
        "fontSize": 20,
        "familyName": "Helvetica",
        "styleName": "Regular"
      }
    }
  }
}

Only part of the configuration is shown as an example. For the complete content, please refer to tools_default_configuration.json

Custom Toolbars

You can control the visibility of toolbars in different modes via toolbarConfig, and customize top toolbar menu items.

  • Show / hide toolbars
json
// tools_default_configuration.json
{
  "toolbarConfig": {
    "mainToolbarVisible": true,               // Show / hide top toolbar
    "contentEditorToolbarVisible": true,      // Show / hide content editor bottom toolbar
    "annotationToolbarVisible": true,         // Show / hide annotation mode bottom toolbar
    "formToolbarVisible": true,               // Show / hide form mode bottom toolbar
    "signatureToolbarVisible": true           // Show / hide signature mode bottom toolbar
  }
}
  • Customize annotation toolbar
json
// tools_default_configuration.json
{
  "annotationsConfig": {
    "annotationAuthor": "Guest",    // Author name of created annotations
    "availableTypes": [             // Enabled annotation types
      "note",
      "highlight",
      "underline",
      "squiggly",
      "strikeout",
      "ink",
      "ink_eraser",
      "circle",
      "square",
      "arrow",
      "line",
      "freetext",
      "signature",
      "stamp",
      "pictures",
      "link",
      "sound"
    ],
    "availableTools": [             // Available tools
      "setting",
      "undo",
      "redo"
    ]
  }
}
  • Customize form toolbar
json
// tools_default_configuration.json
{ 
  "formsConfig": {
    "showCreateListBoxOptionsDialog": true,     // Whether to show options dialog after creating a list box
    "showCreateComboBoxOptionsDialog": true,    // Whether to show options dialog after creating a combo box
    "showCreatePushButtonOptionsDialog": true,  // Whether to show options dialog after creating a button
    "availableTypes": [                         // Enabled form types
      "textField",
      "checkBox",
      "radioButton",
      "listBox",
      "comboBox",
      "signaturesFields",
      "pushButton"
    ],
    "availableTools": [                         // Enabled form tool types
      "undo",
      "redo"
    ]
  }
}
  • Customize top toolbar menu

The default configuration provides a fixed list of menu options, which supports hiding or reordering. Example configuration:

json
// tools_default_configuration.json
{
  "toolbarConfig": {
    "toolbarLeftItems": [
      "back"
    ],
    "toolbarRightItems": [
      "thumbnail",
      "search",
      "bota",
      "menu"
    ],
    "availableMenus": [
      "viewSettings",
      "documentEditor",
      "documentInfo",
      "save",
      "watermark",
      "security",
      "flattened",
      "share",
      "openDocument",
      "snip"
    ]
  }
}

In addition, you can configure custom menu items to meet specific requirements.

  1. Modify menu item icons and text

If you need to modify the icon or text of default menu buttons, you can do so through custom menu configuration. The following example shows how to modify the icon and text of the More menu item in the toolbar:

json
// tools_default_configuration.json
{
  "toolbarConfig": { 
    "customToolbarLeftItems": [],     // Left toolbar items
    "customToolbarRightItems": [],    // Right toolbar items
    "customMoreMenuItems": [          // More menu items
      {
        "action": "viewSettings",     // ID corresponding to view settings
        "icon": "ic_test_settings",   // Button icon, image resource must be placed in res/drawable
        "title": "Settings"           // Menu text
      }
    ]
  }
}

Please note that if custom menu items are configured, the corresponding toolbarLeftItems, toolbarRightItems, and availableMenus configurations will be disabled.

  1. Add custom menu items

You can also add custom buttons as needed. The following example shows how to add a “Download” button to the left toolbar menu. After clicking it, the document is saved and the file path is obtained:

json
// tools_default_configuration.json
{
  "toolbarConfig": { 
    // Left toolbar items
    "customToolbarLeftItems": [
      {
        "action": "custom",                  // The action value of a custom event button must be custom
        "identifier": "custom_download_action", // Unique ID of the custom event, returned in callback when clicked
        "icon": "ic_test_download",          // Button icon, image resource must be placed in res/drawable
        "title": "Download"                  // Only effective in customMoreMenuItems
      }
    ],
    // Right toolbar items
    "customToolbarRightItems": [],
    // More menu items
    "customMoreMenuItems": []
  }
}

Add an event callback when using CPDFDocumentFragment:

java
CPDFDocumentFragment documentFragment = CPDFDocumentFragment.newInstance(uri, "password", configuration);
getSupportFragmentManager()
  .beginTransaction()
  .replace(R.id.fragment_container_view, documentFragment, "documentFragment")
  .commit();

// Add callback
CPDFCustomEventCallbackHelper.getInstance().addCustomEventCallback(extraMap -> {
  // First get the custom event type. There are multiple types, such as toolbar events and context menu events
  String customEventType = extraMap.get(CPDFCustomEventField.CUSTOM_EVENT_TYPE).toString();
  if (CPDFCustomEventType.TOOLBAR_ITEM_TAPPED.equals(customEventType)){
    // Top toolbar button click event
    String action = extraMap.get("identifier").toString();
    switch (action){
      case "custom_download_action":

        CPDFViewCtrl pdfView = documentFragment.pdfView;
        boolean saveIncremental = false;
        boolean fontSubset = true;

        pdfView.savePDF(saveIncremental, fontSubset, (filePath, pdfUri) -> {
          // Get uri or file
          CToastUtil.showToast(getApplicationContext(), "Saved successfully");
        }, e -> {

        });

        break;
    }
  }
});

// Please remove the registered callback after CPDFDocumentFragment is no longer used
CPDFCustomEventCallbackHelper.getInstance().removeCustomEventCallback(this);

By following the steps above, you can add and respond to a fully customized menu button.

custom toolbar menu option

Depending on the type of context menu, different data will be returned in extraMap. Please refer to the following description:

KeyValueDescription
identifiercustom_markup_action_get_textThe option value defined in the custom context menu, a unique identifier
annotationCPDFAnnotationReturned when an annotation is selected
widgetCPDFWidgetReturned when a form field is selected
editAreaCPDFEditAreaReturned when text or images are selected in content editing mode
textxxxThe selected text string when text is long-pressed
pageIndexThe page index where the selected text is located
rectThe bounding rectangle of the selected text
imagebitmapThe Bitmap image of the captured rectangular area from screenshot context
pointThe tap position returned when long-pressing a blank area in content edit mode

Add Callback Events

The ComPDFKit_Tools module provides a series of event callbacks in CPDFDocumentFragment, enabling advanced customization and interaction handling. Below are some commonly used callbacks:


Initialization Completed Callback

java
// Triggered when CPDFDocumentFragment successfully opens and finishes loading the document
documentFragment.setInitListener(pdfView -> {

});

Save Document Callback

java
documentFragment.setInitListener(pdfView -> {
  pdfView.setSaveCallback((filePath, pdfUri) -> {
    // Save succeeded
  }, e -> {
    // Save failed
  });
});

Annotation Creation Callback

java
documentFragment.setAddAnnotCallback(new CPDFAddAnnotCallback() {
  @Override
  public void onAddAnnotation(CPDFPageView cpdfPageView, CPDFBaseAnnotImpl<CPDFAnnotation> cpdfBaseAnnot) {

  }
});

Annotation / Form Selection Callback

java
documentFragment.setInitListener(pdfView -> {
  pdfView.getCPdfReaderView().setSelectAnnotCallback(new CPDFSelectAnnotCallback() {
    @Override
    public void onAnnotationSelected(CPDFPageView cpdfPageView, CPDFBaseAnnotImpl<CPDFAnnotation> cpdfBaseAnnot) {

    }

    @Override
    public void onAnnotationDeselected(
        CPDFPageView cpdfPageView,
        @Nullable CPDFBaseAnnotImpl<CPDFAnnotation> cpdfBaseAnnot) {

    }
  });
});

Content Editor Selection Callback

java
documentFragment.setInitListener(pdfView -> {
  CPDFReaderView readerView = pdfView.getCPdfReaderView();
  pdfView.addSelectEditAreaChangeListener(new OnSelectEditAreaChangeListener() {
    @Override
    public void onSelectEditAreaChange(int type) {
      if (type == CEditToolbar.SELECT_AREA_NONE) {
        return;
      }
      CPDFEditArea editArea = readerView.getSelectEditArea();
    }
  });
});

Fullscreen Toggle Callback

java
documentFragment.setFillScreenChangeListener(fillScreen -> {

});

For more callback interfaces, please refer to CPDFDocumentFragment, CPDFViewCtrl, and CPDFReaderView.