Retrieve or Set the Annotation Bounding Box in Flutter

Each annotation has a size and a position, known as the annotation’s bounding box. To access the bounding box of a given annotation, you need to call getAnnotations(pageIndex, type) (available only in iOS) to get the annotation. Then, you can access its bounding box (bbox). The value of the bounding box is a rect array instance, which holds the annotation’s size and position in PDF coordinates.

The example below shows how to add a button that displays an alert with the value of the bounding box of the first annotation on the first page of the document:

import 'dart:async';

import 'package:flutter/services.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import 'package:pspdfkit_flutter/pspdfkit_widget_controller.dart';

class PspdfkitAnnotationsExampleWidget extends StatefulWidget {
  final String documentPath;
  final dynamic configuration;

  PspdfkitAnnotationsExampleWidget(
      {Key? key, required this.documentPath, this.configuration})
      : super(key: key);

  @override
  _PspdfkitAnnotationsExampleWidgetState createState() =>
      _PspdfkitAnnotationsExampleWidgetState();
}

class _PspdfkitAnnotationsExampleWidgetState
    extends State<PspdfkitAnnotationsExampleWidget> {
  late PspdfkitWidgetController view;

  @override
  Widget build(BuildContext context) {
    // This is used in the platform side to register the view.
    const String viewType = 'com.pspdfkit.widget';
    // Pass parameters to the platform side.
    final Map<String, dynamic> creationParams = <String, dynamic>{
      'document': widget.documentPath,
      'configuration': widget.configuration
    };

    if (defaultTargetPlatform == TargetPlatform.iOS) {
      return CupertinoPageScaffold(
          navigationBar: const CupertinoNavigationBar(),
          child: SafeArea(
              bottom: false,
              child: Column(children: <Widget>[
                Expanded(
                    child: UiKitView(
                        viewType: viewType,
                        layoutDirection: TextDirection.ltr,
                        creationParams: creationParams,
                        onPlatformViewCreated: onPlatformViewCreated,
                        creationParamsCodec: const StandardMessageCodec())),
                SizedBox(
                    height: 80,
                    child: Row(children: <Widget>[
                      Container(width: 20),
                      CupertinoButton(
                          onPressed: () async {
                            dynamic annotations = await view.getAnnotations(0, 'all');
                            await showCupertinoDialog<CupertinoAlertDialog>(
                                context: context,
                                builder: (BuildContext context) =>
                                    CupertinoAlertDialog(
                                      title: const Text('Bounding box'),
                                      content: Text('${annotations[0]['bbox']}'),
                                      actions: [
                                        TextButton(
                                            onPressed: () {
                                              Navigator.of(context).pop();
                                            },
                                            child: const Text('OK'))
                                      ],
                                    ));
                          },
                          child: const Text('Get Bounding Box')),
                      Container(width: 20)
                    ]))
              ])));
    } else if (defaultTargetPlatform == TargetPlatform.android) {
      return Scaffold(
          extendBodyBehindAppBar: true,
          appBar: AppBar(),
          body: SafeArea(
              top: false,
              bottom: false,
              child: Container(
                  padding: const EdgeInsets.only(top: kToolbarHeight),
                  child: Column(children: <Widget>[
                    Expanded(
                        child: PlatformViewLink(
                      viewType: viewType,
                      surfaceFactory: (BuildContext context,
                          PlatformViewController controller) {
                        return AndroidViewSurface(
                          controller: controller as AndroidViewController,
                          gestureRecognizers: const <
                              Factory<OneSequenceGestureRecognizer>>{},
                          hitTestBehavior: PlatformViewHitTestBehavior.opaque,
                        );
                      },
                      onCreatePlatformView:
                          (PlatformViewCreationParams params) {
                        return PlatformViewsService.initSurfaceAndroidView(
                          id: params.id,
                          viewType: viewType,
                          layoutDirection: TextDirection.ltr,
                          creationParams: creationParams,
                          creationParamsCodec: const StandardMessageCodec(),
                          onFocus: () {
                            params.onFocusChanged(true);
                          },
                        )
                          ..addOnPlatformViewCreatedListener(
                              params.onPlatformViewCreated)
                          ..addOnPlatformViewCreatedListener(
                              onPlatformViewCreated)
                          ..create();
                      },
                    )),
                    SizedBox(
                    height: 80,
                    child: Row(children: <Widget>[
                      Container(width: 20),
                      ElevatedButton(
                          onPressed: () async {
                            dynamic annotations = await view.getAnnotations(0, 'all');
                            await showDialog<AlertDialog>(
                                context: context,
                                builder: (BuildContext context) =>
                                    AlertDialog(
                                      title: const Text('Bounding box'),
                                      content: Text('${annotations[0]['bbox']}'),
                                      actions: [
                                        TextButton(
                                            onPressed: () {
                                              Navigator.of(context).pop();
                                            },
                                            child: const Text('OK'))
                                      ],
                                    ));
                          },
                          child: const Text('Get Bounding Box')),
                      Container(width: 20)
                    ]))
                  ]))));
    } else {
      return Text(
          '$defaultTargetPlatform is not yet supported by PSPDFKit for Flutter.');
    }
  }

  Future<void> onPlatformViewCreated(int id) async {
    view = PspdfkitWidgetController(id);
  }
}

Here’s how it looks:

Bounding box alert