Text selection in Flutter PDF Viewer (SfPdfViewer)

11 Dec 202311 minutes to read

On a touch device, the SfPdfViewer allows you to select a text in the PDF page by long pressing on it, which in turn displays the selection handles or bubbles at the top-left and bottom-right corners of its bounds. Then, you can use the left handle to select the text at the left and top, and the right handle to select the text at the right and bottom directions.

And on a desktop web browser, the text selection can also be performed using mouse dragging with the selection interaction mode enabled.

NOTE

The images in the document will not be selected and, the multiple-page text selection is not supported for now.

Enable or disable text selection

You can enable or disable the text selection in the PDF page using the enableTextSelection property. The following code example explains the same.

@override
Widget build(BuildContext context) {
  return Scaffold(
      body: SfPdfViewer.network(
              'https://cdn.syncfusion.com/content/PDFViewer/flutter-succinctly.pdf',
              enableTextSelection: false));
}

NOTE

On a desktop web browser, this enableTextSelection property will have no effect on the pan interaction mode.

Customize the text selection and its handle color

The SfPdfViewer allows you to customize the color used for text selection and its handle based on your requirements. The properties selectionColor and selectionHandleColor of the TextSelectionThemeData class can be used to customize them. The following code example explains the same.

void main() => runApp(MaterialApp(
      title: 'Syncfusion PDF Viewer Demo',
      theme: ThemeData(
        textSelectionTheme: TextSelectionThemeData(
            selectionColor: Colors.red, selectionHandleColor: Colors.blue),
      ),
      home: HomePage(),
    ));

/// Represents Homepage for Navigation
class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Syncfusion Flutter PDF Viewer'),
        ),
        body: Container(
            child: SfPdfViewer.network(
          'https://cdn.syncfusion.com/content/PDFViewer/flutter-succinctly.pdf',
        )));
  }
}

Callbacks

The SfPdfViewer text selection supports the PdfTextSelectionChangedCallback to notify the text selection changes.

Text selection changed callback

The onTextSelectionChanged callback triggers when the text is selected or deselected in the SfPdfViewer. The PdfTextSelectionChangedDetails will hold the globalSelectedRegion representing the global bounds information of the selected text region and the selectedText representing the selected text value. The following code example explains the same.

@override
Widget build(BuildContext context) {
  return Scaffold(
      appBar: AppBar(
        title: Text('Syncfusion Flutter PDF Viewer'),
      ),
      body: SfPdfViewer.network(
        'https://cdn.syncfusion.com/content/PDFViewer/flutter-succinctly.pdf',
        onTextSelectionChanged: (PdfTextSelectionChangedDetails details) {
          if (details.selectedText != null) {
            print(details.selectedText);
          }
        },
      ));
}

How to get the seleted text lines in the PDF viewer?

Using the getSelectedTextLines method, you can get the selected text lines in the PDF viewer. The following code example explains the same.

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text('Syncfusion Flutter PDF Viewer'),
      actions: <Widget>[
        IconButton(
          icon: const Icon(Icons.add),
          onPressed: () async {
            final List<PdfTextLine>? selectedTextLines =
                _pdfViewerKey.currentState?.getSelectedTextLines();

            if (selectedTextLines != null && selectedTextLines.isNotEmpty) {
              // Creates a highlight annotation with the selected text lines.
              final HighlightAnnotation highlightAnnotation =
                  HighlightAnnotation(
                textBoundsCollection: selectedTextLines,
              );
              // Adds the highlight annotation to the PDF document.
              _pdfViewerController.addAnnotation(highlightAnnotation);
            }
          },
        ),
      ],
    ),
    body: SfPdfViewer.asset(
      'assets/sample.pdf',
      key: _pdfViewerKey,
      controller: _pdfViewerController,
    ),
  );
}

How to create and display a customized text selection context menu with a Copy option to retrieve the selected text?

With the options available in the SfPdfViewer text selection, you can easily create and display a customized text selection context menu with the Copy option and perform an operation for the same. The following code example explains the same.

In this example, we have used the OverlayEntry widget to create the customized context menu and have added a simple button (for the Copy option) as a child to it. Whenever this Copy option is pressed, the selected text will be copied to the clipboard and the selection will be cleared. The selected text value is retrieved from the onTextSelectionChanged callback details and we have called the context menu displaying method within this callback implementation. The text selection gets cleared after the Copy operation by calling the clearSelection controller method.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';

void main() => runApp(const MaterialApp(
      title: 'Syncfusion PDF Viewer Demo',
      home: HomePage(),
    ));

/// Represents Homepage for Navigation
class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  late PdfViewerController _pdfViewerController;
  OverlayEntry? _overlayEntry;
  @override
  void initState() {
    _pdfViewerController = PdfViewerController();
    super.initState();
  }

  void _showContextMenu(
      BuildContext context, PdfTextSelectionChangedDetails details) {
    final OverlayState overlayState = Overlay.of(context);
    _overlayEntry = OverlayEntry(
      builder: (context) => Positioned(
        top: details.globalSelectedRegion!.center.dy - 55,
        left: details.globalSelectedRegion!.bottomLeft.dx,
        child: ElevatedButton(
          onPressed: () {
            if (details.selectedText != null) {
              Clipboard.setData(ClipboardData(text: details.selectedText!));
              print('Text copied to clipboard: ${details.selectedText}');
              _pdfViewerController.clearSelection();
            }
          },
          style: ButtonStyle(
            shape: MaterialStateProperty.all(RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(2),
            )),
          ),
          child: const Text('Copy', style: TextStyle(fontSize: 17)),
        ),
      ),
    );
    overlayState.insert(_overlayEntry!);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('Syncfusion Flutter PDF Viewer'),
        ),
        body: SfPdfViewer.network(
          'https://cdn.syncfusion.com/content/PDFViewer/flutter-succinctly.pdf',
          onTextSelectionChanged: (PdfTextSelectionChangedDetails details) {
            if (details.selectedText == null && _overlayEntry != null) {
              _overlayEntry!.remove();
              _overlayEntry = null;
            } else if (details.selectedText != null && _overlayEntry == null) {
              _showContextMenu(context, details);
            }
          },
          controller: _pdfViewerController,
        ));
  }
}