---
title: "Customizing text selection in Android PDF viewer | Nutrient Android SDK"
canonical_url: "https://www.nutrient.io/guides/android/features/text-selection/"
md_url: "https://www.nutrient.io/guides/android/features/text-selection.md"
last_updated: "2026-05-15T19:10:04.924Z"
description: "Learn how to select, copy, and interact with text in our Android PDF viewer. Enhance your app’s user experience with robust text selection functionality."
---

# Selecting text in Android PDF viewer

The [`TextSelectionManager`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.ui.special_mode.manager/-text-selection-manager/index.html) interface provides two listeners:

- [`OnTextSelectionModeChangeListener`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.ui.special_mode.manager/-text-selection-manager/-on-text-selection-mode-change-listener/index.html)

- [`OnTextSelectionChangeListener`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.ui.special_mode.manager/-text-selection-manager/-on-text-selection-change-listener/index.html)

These listeners enable you to monitor text selection changes. The default [`PdfActivity`] implementation displays a contextual toolbar when text is long-pressed and text selection mode starts. This toolbar is called [`TextSelectionToolbar`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.ui.toolbar/-text-selection-toolbar/index.html) and allows you to perform the following five actions with the selected text:

- **Highlight**

- **Speak**

- **Copy to clipboard**

- **Share**

- **Search**

## Registering custom listeners

You can create custom listeners for [`TextSelectionManager`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.ui.special_mode.manager/-text-selection-manager/index.html) to handle changes in text selection and text selection mode (entering and exiting):

### MYACTIVITY.KT

```kt

class MyActivity : PdfActivity(), TextSelectionManager.OnTextSelectionChangeListener, TextSelectionManager.OnTextSelectionModeChangeListener {

  const val TAG = "MyActivity.TextSelection"

  override fun onCreate(savedInstanceState: Bundle?) {
    PdfFragment.addOnTextSelectionModeChangeListener(this)
    PdfFragment.addOnTextSelectionChangeListener(this)
  }

  override fun onDestroy(savedInstanceState: Bundle?) {
    PdfFragment.removeOnTextSelectionModeChangeListener(this)
    PdfFragment.removeOnTextSelectionChangeListener(this)
  }

  override fun onEnterTextSelectionMode(controller: TextSelectionController) {
    Log.i(TAG, "Text selection mode has started.")
  }

  override fun onExitTextSelectionMode(controller: TextSelectionController) {
    Log.i(TAG, "Text selection mode has ended.")
  }

  override fun onTextSelectionChange(newTextSelection: TextSelection?, currentTextSelection: TextSelection?): Boolean {
    if (newTextSelection!= null) {
      Log.i(TAG, "Selected text was: ${newTextSelection.text}")
    } else {
      Log.i(TAG, "Text selection is cleared.")
    }
    // Return `false` to prevent changes to the current selection state, if needed.
    return true
  }
}

```

### MYACTIVITY.JAVA

```java

public class MyActivity extends PdfActivity implements TextSelectionManager.OnTextSelectionChangeListener,
    TextSelectionManager.OnTextSelectionModeChangeListener{

  private static final String TAG = "MyActivity.TextSelection";

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      getPdfFragment().addOnTextSelectionModeChangeListener(this);
      getPdfFragment().addOnTextSelectionChangeListener(this);
  }

  @Override
  protected void onDestroy(Bundle savedInstanceState) {
      getPdfFragment().removeOnTextSelectionModeChangeListener(this);
      getPdfFragment().removeOnTextSelectionChangeListener(this);
  }

  @Override
  public void onEnterTextSelectionMode(@NonNull TextSelectionController controller) {
      Log.i(TAG, "Text selection mode has started.");
  }

  @Override
  public void onExitTextSelectionMode(@NonNull TextSelectionController controller) {
      Log.i(TAG, "Text selection mode has ended.");
  }

  @Override
  public boolean onTextSelectionChange(@Nullable TextSelection newTextSelection, @Nullable TextSelection currentTextSelection) {
      if (newTextSelection!= null) {
          Log.i(TAG, String.format("Selected text was: %s", newTextSelection.text));
      } else {
          Log.i(TAG, "Text selection is cleared.");
      }

      // Return `false` to prevent changes to the current selection state, if needed.
      return true;
  }
}

```

By implementing these listeners, you can add custom reactions to text selection events.

This setup doesn’t override the default behavior — it only adds additional listeners. If you need to completely change the behavior (e.g. replacing the toolbar with a custom user interface), use [`PdfFragment`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.ui/-pdf-fragment/index.html) in a custom activity and bind it to the [`TextSelectionController`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.ui.special_mode.controller/-text-selection-controller/index.html).





## Customize text selection actions

You can modify existing text selection actions or add new ones using [`toolbar.setMenuItems(...)`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.ui.toolbar/-contextual-toolbar/menu-items.html). To access the [`TextSelectionToolbar`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.ui.toolbar/-text-selection-toolbar/index.html), register the [`OnContextualToolbarLifecycleListener`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.ui.toolbar/-toolbar-coordinator-layout/-on-contextual-toolbar-lifecycle-listener/index.html) and configure actions in its [`#onPrepareContextualToolbar`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.ui.toolbar/-toolbar-coordinator-layout/-on-contextual-toolbar-lifecycle-listener/on-prepare-contextual-toolbar.html) method:

### MYACTIVITY.KT

```kt

class MyActivity : PdfActivity(), ToolbarCoordinatorLayout.OnContextualToolbarLifecycleListener {

    private lateinit var customTextSelectionAction: ContextualToolbarMenuItem

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

        // Register the activity as a callback for contextual toolbar changes.
        // It will be called once the `TextSelectionToolbar` is going to be presented.
        setOnContextualToolbarLifecycleListener(this)

        // Create a custom menu item that will be shown inside the text selection toolbar.
        customTextSelectionAction = ContextualToolbarMenuItem.create(
            this,
            R.id.custom_text_action,
            AppCompatDrawableManager.get().getDrawable(this, R.drawable.ic_my_action),
            "Custom text action",
            Color.WHITE,
            Color.RED,
            false)
    }

    override fun onPrepareContextualToolbar(toolbar: ContextualToolbar) {
        // Add the custom action once the selection toolbar is being prepared.
        // At this point, you could also remove undesired actions from the toolbar.
        if (toolbar is TextSelectionToolbar) {
            val menuItems = toolbar.getMenuItems()
            if (!menuItems.contains(customTextSelectionAction)) {
                menuItems.add(customTextSelectionAction)
                toolbar.setMenuItems(menuItems)
            }
        }
    }

    override fun onDisplayContextualToolbar(toolbar: ContextualToolbar) {
        // Register a click listener to handle taps on the custom text selection action.
        toolbar.setOnMenuItemClickListener { toolbar, menuItem ->
            var handled = false

            if (menuItem.id == R.id.custom_text_action) {
                handled = true
                Toast.makeText(this@MyActivity, "Text selection action triggered!", Toast.LENGTH_SHORT).show()
            }

            handled
        }
    }

    override fun onRemoveContextualToolbar(toolbar: ContextualToolbar) {
        toolbar.setOnMenuItemClickListener(null)
    }
}

```

### MYACTIVITY.JAVA

```java

public class MyActivity extends PdfActivity
    implements ToolbarCoordinatorLayout.OnContextualToolbarLifecycleListener {

    private ContextualToolbarMenuItem customTextSelectionAction;

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

        // Register the activity as a callback for contextual toolbar changes.
        // It will be called once the `TextSelectionToolbar` is going to be presented.
        setOnContextualToolbarLifecycleListener(this);

        // Create a custom menu item that will be shown inside the text selection toolbar.
        customTextSelectionAction = ContextualToolbarMenuItem.create(
            this,
            R.id.custom_text_action,
            AppCompatDrawableManager.get().getDrawable(this, R.drawable.ic_my_action),
            "Custom text action",
            Color.WHITE,
            Color.RED,
            false
        );
    }

    @Override public void onPrepareContextualToolbar(@NonNull ContextualToolbar toolbar) {
        // Add the custom action once the selection toolbar is being prepared.
        // At this point, you could also remove undesired actions from the toolbar.
        if (toolbar instanceof TextSelectionToolbar) {
            final List<ContextualToolbarMenuItem> menuItems = toolbar.getMenuItems();
            if (!menuItems.contains(customTextSelectionAction)) {
                menuItems.add(customTextSelectionAction);
                toolbar.setMenuItems(menuItems);
            }
        }
    }

    @Override public void onDisplayContextualToolbar(@NonNull ContextualToolbar toolbar) {
        // Register a click listener to handle taps on the custom text selection action.
        toolbar.setOnMenuItemClickListener((contextualToolbar, menuItem) -> {
            boolean handled = false;

            if (menuItem.getId() == R.id.custom_text_action) {
                handled = true;
                Toast.makeText(MyActivity.this, "Text selection action triggered!", Toast.LENGTH_SHORT).show();
            }

            return handled;
        });
    }

    @Override public void onRemoveContextualToolbar(@NonNull ContextualToolbar toolbar) {
        toolbar.setOnMenuItemClickListener(null);
    }
}

```

This approach allows you to add custom actions to the toolbar or remove existing ones when the toolbar is prepared.

## Selecting text programmatically

You can programmatically select text using the [`PdfFragment#enterTextSelectionMode`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.ui/-pdf-fragment/enter-text-selection-mode.html) method and specifying the text range to be selected. You can retrieve the text of the current page by calling the [`PdfDocument#getPageText`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.document/-pdf-document/get-page-text.html) method.

For example, to select the first occurrence of a string on the page, use the following code:

### KOTLIN

```kotlin

// Search for the position of text that should be selected.
val textToSelect = "text to select"
val textIndexOnPage = document.getPageText(pageIndex).indexOf(textToSelect)
if (textIndexOnPage >= 0) {
    // Select the text.
    fragment.enterTextSelectionMode(pageIndex, Range(textIndexOnPage, textToSelect.length))
}

```

### JAVA

```java

// Search for the position of text that should be selected.
String textToSelect = "text to select";
int textIndexOnPage = document.getPageText(pageIndex).indexOf(textToSelect);
if (textIndexOnPage >= 0) {
    // Select the text.
    fragment.enterTextSelectionMode(pageIndex, new Range(textIndexOnPage, textToSelect.length()));
}

```





Alternatively, you can select text by providing a list of rectangles, and the text beneath these rectangles will be selected. Use the `TextSelectionRectangles` object, which is created in one of the following ways:

- Provide a list of rectangles (no markup padding applied).

- Provide a list of rectangles with markup padding.

### KOTLIN

```kotlin

fragment.enterTextSelectionMode(pageIndex, TextSelectionRectangles(rectangles, markupRectangles))

```

### JAVA

```java

fragment.enterTextSelectionMode(pageIndex, new TextSelectionRectangles(rectangles, markupRectangles));

```

Nutrient Android SDK throws an `IllegalStateException` in the following scenarios:

- Invalid parameters are provided.

- The text range exceeds the available text on the page.

- No text exists beneath the specified rectangles.
---

## Related pages

- [Android image viewer library](/guides/android/viewer/images.md)
- [Android PDF viewer library](/guides/android/viewer.md)
- [Create efficient Android PDF viewers for apps](/guides/android/viewer/java.md)
- [Customizing page navigation in our Android PDF viewer](/guides/android/basics/document-interactions.md)
- [Configuring scroll directions and page transitions in our Android viewer](/guides/android/customizing-the-interface/document-presentation-options.md)
- [Mastering PDF permissions in Android apps](/guides/android/viewer/permissions.md)
- [Enhance your Android PDF viewer with JavaScript support](/guides/android/features/javascript.md)
- [Android PDF  iewer troubleshooting](/guides/android/viewer/troubleshooting.md)
- [Fast and feature-rich PDF viewer for Android apps](/guides/android/viewer/kotlin.md)
- [Customizing zoom options in our Android PDF viewer](/guides/android/miscellaneous/zooming.md)
- [Using the view state to display PDFs on Android](/guides/android/view-management/store-load-view-state.md)

