Customizing the Toolbar

PSPDFKit comes with a flexible toolbar system that provides basic action bar functionality, as well as powerful editing features.

Styling the Toolbar

By default, PSPDFKit will apply default styles to all of its toolbars. A large set of style attributes allows you to modify the appearance of toolbars according to your app’s look. Check out the styling guide, which gives an overview of all available style attributes.

Change the Grouping of Toolbar Items

Each toolbar contains ContextualToolbarMenuItems representing toolbar elements/items.

The rules of how menu items in each toolbar are grouped are defined in classes extending PresetMenuItemGroupingRule, which you can set through setMenuItemGroupingRule() called on the specific toolbar. What you want to do is override PresetMenuItemGroupingRule#getGroupPreset(), returning a different structure depending on the given toolbar capacity.

MenuItem represents a structure, using IDs for identification, of how ContextualToolbarMenuItems with those IDs would be positioned/grouped. For more details on the implementation, check out CustomToolbarIconGroupingExample in the Catalog app.

Custom toolbar grouping: A markup item group, a color picker, a custom menu item, and an image picker, all defined in a custom grouping structure.

For example, let’s define a custom grouping of menu items for AnnotationCreationToolbar, but with our own added custom item:

Copy
MyCustomGrouping.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class MyCustomGrouping(context: Context) : PresetMenuItemGroupingRule(context) {

    override fun getGroupPreset(capacity: Int, itemsCount: Int): List<MenuItem> {
        // The capacity shouldn't be less than 4. If that is the case, return an empty list.
        if (capacity < ContextualToolbar.MIN_TOOLBAR_CAPACITY) return emptyList<MenuItem>()

        return if (capacity <= 7) FOUR_ITEMS_GROUPING else SEVEN_ITEMS_GROUPING
    }

    /** Annotation toolbar grouping with 4 elements. */
    private val FOUR_ITEMS_GROUPING = listOf(
            MenuItem(R.id.pspdf_menu_custom),
            MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_markup,
                    intArrayOf(
                        com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_highlight,
                        com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_squiggly,
                        com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_strikeout,
                        com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_underline))
            MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_picker),
            MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_image)
            )

    /** Annotation toolbar grouping with 7 elements. */
    private val SEVEN_ITEMS_GROUPING = listOf(
            MenuItem(R.id.pspdf_menu_custom),
            MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_highlight),
            MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_squiggly),
            MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_strikeout),
            MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_underline),
            MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_picker),
            MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_image)
        )

}
Copy
MyCustomGrouping.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class MyCustomGrouping extends PresetMenuItemGroupingRule {

    public CustomAnnotationCreationToolbarGroupingRule(@NonNull Context context) {
        super(context);
    }

    @Override
    public List<MenuItem> getGroupPreset(@IntRange(from = ContextualToolbar.MIN_TOOLBAR_CAPACITY) int capacity, int itemsCount) {
        // The capacity shouldn't be less than 4. If that is the case, return an empty list.
        if (capacity < ContextualToolbar.MIN_TOOLBAR_CAPACITY) return new ArrayList<>(0);

        return (capacity <= 7) ? FOUR_ITEMS_GROUPING : SEVEN_ITEMS_GROUPING;
    }

    /** Annotation toolbar grouping with 4 elements. */
    private static final List<MenuItem> FOUR_ITEMS_GROUPING = new ArrayList<>(4);
    static {
        // Make sure our custom item is included.
        FOUR_ITEMS_GROUPING.add(new MenuItem(R.id.pspdf_menu_custom));
        FOUR_ITEMS_GROUPING.add(new MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_markup,
                new int[]{
                        com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_highlight,
                        com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_squiggly,
                        com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_strikeout,
                        com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_underline}));
        FOUR_ITEMS_GROUPING.add(new MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_picker));
        FOUR_ITEMS_GROUPING.add(new MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_image));
    }

    /** Annotation toolbar grouping with 7 elements. */
    private static final List<MenuItem> SEVEN_ITEMS_GROUPING = new ArrayList<>(7);
    static {
        // Make sure our custom item is included.
        SEVEN_ITEMS_GROUPING.add(new MenuItem(R.id.pspdf_menu_custom));
        SEVEN_ITEMS_GROUPING.add(new MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_highlight));
        SEVEN_ITEMS_GROUPING.add(new MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_squiggly));
        SEVEN_ITEMS_GROUPING.add(new MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_strikeout));
        SEVEN_ITEMS_GROUPING.add(new MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_underline));
        SEVEN_ITEMS_GROUPING.add(new MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_picker));
        SEVEN_ITEMS_GROUPING.add(new MenuItem(com.pspdfkit.R.id.pspdf__annotation_creation_toolbar_item_image));
    }

}

Now let’s create an activity where we can listen to the annotation creation toolbar being displayed and apply our own structure and add a custom item to it:

Copy
MyCustomActivity.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class MyCustomActivity : PdfActivity(), ToolbarCoordinatorLayout.OnContextualToolbarLifecycleListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setOnContextualToolbarLifecycleListener(this)
    }

    override fun onPrepareContextualToolbar(toolbar: ContextualToolbar<*>) {
        if (toolbar is AnnotationCreationToolbar) {
            toolbar.setMenuItemGroupingRule(CustomAnnotationCreationToolbarGroupingRule(this))

            // Get the existing menu items so we can add our item later.
            val menuItems = toolbar.menuItems

            // Create our custom menu item.
            val customItem = ContextualToolbarMenuItem.createSingleItem(
                this,
                R.id.pspdf_menu_custom,
                ContextCompat.getDrawable(this, R.drawable.ic_bookmark_outline),
                "Bookmark",
                Color.WHITE,
                Color.WHITE,
                ContextualToolbarMenuItem.Position.START,
                false
            )

            // Tell the toolbar about our new item.
            menuItems.add(customItem)
            toolbar.setMenuItems(menuItems)

            // Add a listener so we can handle clicking on our item.
            toolbar.setOnMenuItemClickListener(ContextualToolbar.OnMenuItemClickListener { toolbar, menuItem -> {
                if (menuItem.id == R.id.pspdf_menu_custom) {
                    Toast.makeText(this@MyCustomActivity, "Custom Action clicked", Toast.LENGTH_SHORT).show()
                    return true
                }
                return false
            }})
        }
    }

    ...

}
Copy
MyCustomActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class MyCustomActivity extends PdfActivity implements ToolbarCoordinatorLayout.OnContextualToolbarLifecycleListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setOnContextualToolbarLifecycleListener(this);
    }

    @Override
    public void onPrepareContextualToolbar(@NonNull ContextualToolbar toolbar) {
        if (toolbar instanceof AnnotationCreationToolbar) {
            toolbar.setMenuItemGroupingRule(new CustomAnnotationCreationToolbarGroupingRule(this));

            // Get the existing menu items so we can add our item later.
            final List<ContextualToolbarMenuItem> menuItems = ((AnnotationCreationToolbar) toolbar).getMenuItems();

            // Create our custom menu item.
            final ContextualToolbarMenuItem customItem = ContextualToolbarMenuItem.createSingleItem(
                this,
                R.id.pspdf_menu_custom,
                ContextCompat.getDrawable(this, R.drawable.ic_bookmark_outline),
                "Bookmark",
                Color.WHITE,
                Color.WHITE,
                ContextualToolbarMenuItem.Position.START,
                false
            );

            // Tell the toolbar about our new item.
            menuItems.add(customItem);
            toolbar.setMenuItems(menuItems);

            // Add a listener so we can handle clicking on our item.
            toolbar.setOnMenuItemClickListener(new ContextualToolbar.OnMenuItemClickListener() {
                @Override
                public boolean onToolbarMenuItemClick(@NonNull ContextualToolbar toolbar, @NonNull ContextualToolbarMenuItem menuItem) {
                    if (menuItem.getId() == R.id.pspdf_menu_custom) {
                        Toast.makeText(MyCustomActivity.this, "Custom Action clicked", Toast.LENGTH_SHORT).show();
                        return true;
                    }
                    return false;
                }
            });
        }
    }


}

Toolbar Positions

You can programmatically set the position of a toolbar or lock the toolbar into a specific position using ToolbarCoordinatorLayout.LayoutParams. To set the toolbar to a specific position, you can call setPosition() directly on the toolbar instance you want to move:

Copy
MyPdfActivity.kt
1
2
3
4
5
6
7
8
9
10
11
12
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // This example will move every toolbar that is shown to the user to the right position.
    setOnContextualToolbarLifecycleListener(object : OnContextualToolbarLifecycleListener {
        override fun onPrepareContextualToolbar(toolbar: ContextualToolbar) {
            toolbar.position = ToolbarCoordinatorLayout.LayoutParams.Position.RIGHT
        }

        ...
    })
}
Copy
MyPdfActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
@Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // This example will move every toolbar that is shown to the user to the right position.
    setOnContextualToolbarLifecycleListener(new OnContextualToolbarLifecycleListener() {
        @Override public void onPrepareContextualToolbar(@NonNull ContextualToolbar toolbar) {
            toolbar.setPosition(ToolbarCoordinatorLayout.LayoutParams.Position.RIGHT);
        }

        ...
    });
}

Lock Toolbar into Position

You can also permanently lock a toolbar to a specific position by limiting the allowedPositions using the toolbar’s ToolbarCoordinatorLayout.LayoutParams:

Copy
MyPdfActivity.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // This example will lock every toolbar to the left position,
    // making you unable to drag the toolbar to a different position.
    setOnContextualToolbarLifecycleListener(object : OnContextualToolbarLifecycleListener {
        override fun onPrepareContextualToolbar(toolbar: ContextualToolbar) {
            toolbar.layoutParams = ToolbarCoordinatorLayout.LayoutParams(
                Position.LEFT, EnumSet.of(Position.LEFT)
            ))
        }

        ...
    })
}
Copy
MyPdfActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // This example will lock every toolbar to the left position,
    // making you unable to drag the toolbar to a different position.
    setOnContextualToolbarLifecycleListener(new OnContextualToolbarLifecycleListener() {
        @Override public void onPrepareContextualToolbar(@NonNull ContextualToolbar toolbar) {
            toolbar.setLayoutParams(new ToolbarCoordinatorLayout.LayoutParams(
                Position.LEFT, EnumSet.of(Position.LEFT)
            ));
        }

        ...
    });
}