Customizing the Toolbar

PSPDFKit comes with a flexible toolbar system providing 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 toolbars 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.

List of MenuItem represents a structure, using ids for identification, of how ContextualToolbarMenuItems with those ids would be positioned/grouped.

Custom toolbar grouping: Custom menu item, followed by markup item group and image picker, all defined in a custom grouping structure.

For example, let's define a custom grouping of menu items for AnnotationCreationToolbar, 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> {
        // Capacity shouldn't be less than 4. If that is the case, return 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) {
        // Capacity shouldn't be less than 4. If that is the case, return 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 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;
                }
            });
        }
    }


}

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 CustomToolbarIconGroupingExample in PSPDFKit catalog app.

Toolbar positions

You can programmatically set the position of a toolbar, or lock the toolbar into a specific position using the 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 to position

You can also permanently lock a toolbar to a specific position, by limiting the allowedPositions using the toolbars 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 it 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 it 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)
            ));
        }

        ...
    });
}