Creating a custom PDF viewer tool in Android

The sample code for this guide can be found at our GitHub repository.

Overview

The tools package provides several base classes that can be extended to create and add custom tools to the viewer. Click here for a complete list of tools.

In this guide, we will create a custom rectangular cloudy annotation tool for either PDFViewCtrl or PdfViewCtrlTabHostFragment2. It is recommended to read the following articles before continuing this guide:

Step 1: Pick a base tool class to inherit

From this tool hiearchy list, find a base tool class to extend. For example, here are some of the more commonly used base tool classes:

Tool

Description

TextMarkupCreate

Creates a text markup annotation. Derive from this class to create annotation on text. Override createMarkup to create an Annot object.

RectCreate

Draws and creates a rectangle annotation. Derive from this class to draw rectangles, for example, checkbox form field. Override createMarkup to create an Annot object.

OvalCreate

Draws and creates an ellipse annotation. Derive from this class if draw ellipses. Override createMarkup to create an Annot object.

SimpleShapeCreate

Creates various shape annotations such as rectangle, ellipse, ink line and more . Use this class if none of the above works for you. Override createMarkup to create an Annot object.

For our custom rectangular cloudy annotation tool, we'll be creating a class called CustomTool that inherits from RectCreate.

Step 2: Override the base class methods

  1. In the CustomTool class, override the getToolMode() method. This method must return a custom tool mode, which can be created by calling ToolManager.ToolMode.addNewMode(int) and specifying the custom tool's annotation type.
  2. Afterwards, override the feature specific methods and implement the desired custom behavior. Add @Keep so the tool can work properly in release mode. For example here is a custom tool that handles creating rectangular cloudy annotations:
1import com.pdftron.pdf.utils.Utils;
2import com.pdftron.pdf.Point;
3import com.pdftron.pdf.Rect;
4// ...
5
6/**
7* This class is to create a rectangular cloudy annotation.
8*/
9@Keep
10public class CustomTool extends RectCreate {
11
12 // Since this tool creates polygon annotation, use Annot.e_Polygon as parameter.
13 public static ToolManager.ToolModeBase MODE =
14 ToolManager.ToolMode.addNewMode(Annot.e_Polygon);
15
16 public CustomTool(@NonNull PDFViewCtrl ctrl) {
17 super(ctrl);
18 }
19
20 @Override
21 public ToolManager.ToolModeBase getToolMode() {
22 return MODE;
23 }
24
25 @Override
26 protected Annot createMarkup(PDFDoc doc, Rect bbox) throws PDFNetException {
27 Polygon poly = new Polygon(Polygon.create(doc, Annot.e_Polygon, bbox));
28 ColorPt color = Utils.color2ColorPt(Color.RED);
29 poly.setColor(color, 3);
30 poly.setVertex(0, new Point(bbox.getX1(), bbox.getY1()));
31 poly.setVertex(1, new Point(bbox.getX1(), bbox.getY2()));
32 poly.setVertex(2, new Point(bbox.getX2(), bbox.getY2()));
33 poly.setVertex(3, new Point(bbox.getX2(), bbox.getY1()));
34 poly.setIntentName(PolyLine.e_PolygonCloud);
35 poly.setBorderEffect(Markup.e_Cloudy);
36 poly.setBorderEffectIntensity(2.0);
37 poly.setRect(bbox);
38
39 return poly;
40 }
41}

Step 3: Register the custom tool in ToolManager

All tools are controlled by an instance of ToolManager and it will need to know about the new custom tool before the tool can be used in the viewer.

  • A PdfViewCtrlTabHostFragment2 contains an internal reference to ToolManager. A custom tool can be added to this internal ToolManager by using the ToolManagerBuilder class. A ToolManagerBuilder object is passed to an instance of ViewerConfig and used to initialize the viewer with the custom tool. The following method can be called in an activity to add a custom tool to a PdfViewCtrlTabHostFragment2:

Option 1: Register using PdfViewCtrlTabHostFragment2

1// Add a custom tool to ViewerConfig and use it to initialize a PdfViewCtrlTabHostFragment2
2public PdfViewCtrlTabHostFragment2 addCustomTool(@NonNull Context context, @NonNull Uri fileUri) {
3 // Create the ToolManagerBuilder builder and add our custom tool
4 ToolManagerBuilder toolManagerBuilder = ToolManagerBuilder
5 .from()
6 .addCustomizedTool(CustomTool.MODE, CustomTool.class);
7 // Add the ToolManagerBuilder builder to a ViewerConfig, that will
8 // be used to initialize PdfViewCtrlTabHostFragment2
9 ViewerConfig config = new ViewerConfig.Builder()
10 .toolManagerBuilder(toolManagerBuilder)
11 .build();
12 // Create the custom PdfViewCtrlTabHostFragment2 using the custom ViewerConfig object
13 return ViewerBuilder2.withUri(fileUri)
14 .usingConfig(config)
15 .build(context);
16}
  • Alternatively if PDFViewCtrl is used and set up with a ToolManager, you can simply add the custom tool directly to ToolManager by calling:

Option 2: Register using PDFViewCtrl

1// Add a custom tool to ToolManager using PDFViewCtrl
2public void addCustomTool(@NonNull ToolManager toolManager, @NonNull PDFViewCtrl pdfViewCtrl) {
3 // Create our custom tool
4 Tool customTool = new CustomTool(pdfViewCtrl);
5 // Then add it to ToolManager
6 toolManager.addCustomizedTool(customTool);
7}

You can learn more about setting up PDFViewCtrl with ToolManager in the ToolManager customization guide .

Step 4: Use the custom tool

To use the custom tool, set it to an instance of ToolManager as follows:

Option 1: Using PdfViewCtrlTabHostFragment2

1public void useCustomTool(@NonNull PdfViewCtrlTabHostFragment2 fragment) {
2 // Create our custom tool
3 ToolManager toolManager = fragment.getCurrentPdfViewCtrlFragment().getToolManager();
4 ToolManager.Tool customTool = toolManager.createTool(CustomTool.MODE, toolManager.getTool());
5 // Then set it in ToolManager
6 toolManager.setTool(customTool);
7}

Option 2: Using PDFViewCtrl

1public void useCustomTool(@NonNull ToolManager toolManager, @NonNull PDFViewCtrl pdfViewCtrl) {
2 // Create our custom tool
3 Tool customTool = new CustomTool(pdfViewCtrl);
4 // Then add it to ToolManager
5 toolManager.addCustomizedTool(customTool);
6}

Now, when using the custom tool you will see the following:

Apryse Docs Image

Step 5: Switch to another tool during motion events

You will be able to switch tool modes within the same tool class in response to a motion event, such as onDown(MotionEvent), onDoubleTap(MotionEvent) and so on.

In gesture event functions, if one tool switches to another tool, that motion event will continue to be executed in the next tool (see tools overview for more information). So if the custom tool wants to switch to another tool during a motion event, you can set the next tool mode by calling Tool.safeSetNextToolMode(ToolMode).

For example, let's override onSingleTapConfirmed in CustomTool.java, and set the next tool to be TextHighlightCreate:

1@Override
2public boolean onSingleTapConfirmed(MotionEvent e) {
3 mNextToolMode = safeSetNextToolMode(ToolManager.ToolMode.TEXT_HIGHLIGHT);
4 return false;
5}

Now in response to a single tap while using your custom tool, it will switch to the TextHighlightCreate tool.

If you need to save the ToolMode and retrieve it at a later time, you can call toString() on the ToolMode object and retrieve the instance later by calling ToolMode.valueOf(String).

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales