This example shows how to modify the default set of ActionBar icons to your app’s needs.


/*
* Copyright © 2018-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.kotlin
import android.content.Context
import android.net.Uri
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.DrawableCompat
import androidx.core.view.get
import androidx.core.view.size
import com.pspdfkit.catalog.R
import com.pspdfkit.catalog.SdkExample
import com.pspdfkit.catalog.tasks.ExtractAssetTask
import com.pspdfkit.configuration.activity.PdfActivityConfiguration
import com.pspdfkit.ui.PdfActivity
import com.pspdfkit.ui.PdfActivityIntentBuilder
/**
* This example shows how to use the Kotlin language to configure a custom [com.pspdfkit.ui.PdfActivity]. Kotlin is a JVM-compatible programming language and
* the second by Google supported programming language for developing Android apps (see introduction: https://developer.android.com/kotlin/index.html).
*/
class CustomActionsExample(context: Context) : SdkExample(context, R.string.customActionsExampleTitle, R.string.customActionsExampleDescription) {
override fun launchExample(context: Context, configuration: PdfActivityConfiguration.Builder) {
// We use a custom utility class to extract the example document from the assets.
ExtractAssetTask.extract(SdkExample.WELCOME_DOC, title, context) { documentFile ->
val intent = PdfActivityIntentBuilder.fromUri(context, Uri.fromFile(documentFile))
.configuration(configuration.build())
.activityClass(CustomActionsActivity::class)
.build()
// You can add your own intent extras to the activity too.
intent.putExtra(CustomActionsActivity.STRING_SAMPLE_ARG, "This toast message is passed via intent extras.")
// Start the CustomActionsActivity for the extracted document.
context.startActivity(intent)
}
}
}
/**
* This subclass of [PdfActivity] adds a set of custom actions.
*/
class CustomActionsActivity : PdfActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Access any previously added intent extras as with normal activities.
val receivedString = intent.getStringExtra(STRING_SAMPLE_ARG)
Toast.makeText(this, receivedString, Toast.LENGTH_SHORT).show()
}
/**
* Override this method to get the list od menu item ids as they're gonna be ordered by default
* so you can add your own menu item ids that you can later edit in [.onCreateOptionsMenu]
* or [.onPrepareOptionsMenu].
*/
override fun onGenerateMenuItemIds(menuItems: MutableList<Int>): List<Int> {
// For example let's say we want to add custom menu items after the outline button.
// First, we get an index of outline button (all default button ids can be retrieved
// via MENU_OPTION_* variables defined in the PdfActivity.
val indexOfOutlineButton = menuItems.indexOf(PdfActivity.MENU_OPTION_OUTLINE)
// Generate our custom item ids.
val customItems = ArrayList<Int>()
customItems.add(R.id.custom_action1)
customItems.add(R.id.custom_action2)
customItems.add(R.id.custom_action3)
// Add items after the outline button.
menuItems.addAll(indexOfOutlineButton + 1, customItems)
// Return new menu items order.
return menuItems
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// This will populate menu with items ordered as specified in onGenerateMenuItemIds().
super.onCreateOptionsMenu(menu)
// Edit first button.
val menuItem1 = menu.findItem(R.id.custom_action1)
menuItem1.title = "Menu Item 1"
menuItem1.setIcon(R.drawable.ic_arrow_left)
// Edit second button.
val menuItem2 = menu.findItem(R.id.custom_action2)
menuItem2.title = "Menu Item 2"
menuItem2.setIcon(R.drawable.ic_arrow_right)
// Edit third button.
val menuItem3 = menu.findItem(R.id.custom_action3)
menuItem3.title = "Menu Item 3"
menuItem3.setIcon(R.drawable.ic_collaborate)
// Let's say we want to tint icons same as the default ones). We can read the color
// from the theme, or specify the same color we have in theme. Reading from theme is a bit
// more complex but a better way to do it, so here's how to:
val a = theme.obtainStyledAttributes(
null,
com.pspdfkit.R.styleable.pspdf__ActionBarIcons,
com.pspdfkit.R.attr.pspdf__actionBarIconsStyle,
com.pspdfkit.R.style.PSPDFKit_ActionBarIcons
)
val mainToolbarIconsColor = a.getColor(com.pspdfkit.R.styleable.pspdf__ActionBarIcons_pspdf__iconsColor, ContextCompat.getColor(this, com.pspdfkit.R.color.pspdf__onPrimary))
a.recycle()
// Tinting all custom menu drawables (you can do it the easier way if you iterate over your ids).
val icon1 = menuItem1.icon
icon1?.let { DrawableCompat.setTint(it, mainToolbarIconsColor) }
menuItem1.icon = icon1
val icon2 = menuItem2.icon
icon2?.let { DrawableCompat.setTint(it, mainToolbarIconsColor) }
menuItem2.icon = icon2
val icon3 = menuItem3.icon
icon3?.let { DrawableCompat.setTint(it, mainToolbarIconsColor) }
menuItem3.icon = icon3
// All our menu items are marked as SHOW_AS_ALWAYS. If you want to just show the first 4
// items for example and send others to the overflow, you can simply do:
for (i in 0 until menu.size) {
menu[i].setShowAsAction(if (i < 4) MenuItem.SHOW_AS_ACTION_IF_ROOM else MenuItem.SHOW_AS_ACTION_NEVER)
}
return true
}
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
// Here, you can edit your items when the menu is being invalidated.
// To invalidate menu, call supportInvalidateOptionsMenu();
return super.onPrepareOptionsMenu(menu)
}
/**
* Override onOptionsItemSelected(MenuItem) to handle click events for your custom menu items.
*/
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val handled = when (item.itemId) {
R.id.custom_action1 -> {
Toast.makeText(this, "Selected Action 1", Toast.LENGTH_SHORT).show()
true
}
R.id.custom_action2 -> {
Toast.makeText(this, "Selected Action 2", Toast.LENGTH_SHORT).show()
true
}
R.id.custom_action3 -> {
Toast.makeText(this, "Selected Action 3", Toast.LENGTH_SHORT).show()
true
}
else -> {
false
}
}
// Return true if you have handled the current event. If your code has not handled the event,
// pass it on to the superclass. This is important or standard Nutrient actions won't work.
return handled || super.onOptionsItemSelected(item)
}
companion object {
const val STRING_SAMPLE_ARG = "some_string_extra"
}
}

This code sample is an example that illustrates how to use our SDK. Please adapt it to your specific use case.