Реализация аннотирования документов в мобильном приложении
PDF-редактор на мобильном — это не просто рисование поверх изображения. Аннотации должны встраиваться в структуру PDF-файла, масштабироваться без потери позиций при изменении зума и сохраняться так, чтобы их мог прочитать Adobe Acrobat. Вот где большинство реализаций проваливаются.
Типы аннотаций и их техническая реализация
Стандарт PDF 1.7 (ISO 32000) определяет типы аннотаций: /Text (стикер), /Highlight, /Underline, /StrikeOut, /Ink (свободное рисование), /FreeText, /Square, /Circle, /Stamp. Реализовывать их как оверлей поверх UIImageView — антипаттерн: при перерендере страницы позиции сбиваются. Аннотации должны храниться в координатах PDF-пространства (точки PDF, не пиксели экрана).
iOS. PDFKit (доступен с iOS 11) — нативный фреймворк с PDFAnnotation. Создаём аннотацию:
let annotation = PDFAnnotation(bounds: bounds, forType: .highlight, withProperties: nil)
annotation.color = UIColor.yellow.withAlphaComponent(0.5)
page.addAnnotation(annotation)
Координаты bounds — в PDF-пространстве страницы. Пересчёт из touch-координат: pdfView.convert(touchPoint, to: page). Для Ink-аннотации собираем [UIBezierPath] и передаём через annotation.paths. Сохранение: document.write(to: url) — встроит аннотации в PDF-структуру.
Android. Нативного PDF-редактора нет. Популярные пути: PdfiumAndroid для рендеринга + собственный Canvas-оверлей с сохранением через iText7 или PDFBox. iText7 (Community, AGPL) умеет добавлять аннотации в существующий PDF через PdfAnnotation. Коммерческий вариант — PdfTron/Apryse SDK: полный стандарт ISO 32000, работает офлайн.
Flutter. syncfusion_flutter_pdfviewer + syncfusion_flutter_pdf (платные для production) или pdfx для рендеринга + ручная реализация через CustomPainter. Бесплатного полного решения нет — либо платный SDK, либо нативный plugin.
Самая сложная часть: Ink-аннотации и стилус
Свободное рисование пальцем работает нормально. Стилус (Apple Pencil, Samsung S Pen) — другая история.
На iOS Apple Pencil даёт UITouch.force и UITouch.azimuthAngle. Для realistic drawing: меняем толщину линии от силы нажатия, применяем сглаживание через алгоритм Catmull-Rom spline между точками. Без сглаживания линия при быстром движении выглядит угловатой — UITouch не успевает передать все промежуточные точки.
Оптимизация рендеринга: не перерисовываем всю страницу на каждый touchesMoved. Используем setNeedsDisplayInRect с bounding box последнего отрезка. На сложных документах полная перерисовка дроп FPS до 20-30, incremental — держит 60.
Подсветка текста (Highlight) поверх PDF
Для корректного highlight нужно знать координаты слов в PDF. PDFPage.selectionForRange и PDFSelection дают PDFPage.characterBounds(at:) для каждого символа. Highlight рисуем не прямоугольником всей выделенной области, а набором прямоугольников по строкам — иначе на многострочном выделении получается один широкий блок вместо аккуратных полосок.
Экспорт и совместимость
После редактирования пользователь ожидает получить PDF, который откроется в любом ридере. PDFKit.document.write(to:) на iOS это гарантирует. На Android iText7 записывает стандартные аннотации. Проблема возникает с custom stamps и SVG-изображениями — их нужно растеризовать перед встройкой.
Шаринг: UIActivityViewController на iOS, FileProvider + Intent.ACTION_SEND на Android.
Сроки
Базовый набор (highlight, underline, freetext, ink) на одну платформу — 3-4 дня. Полный редактор с поддержкой стилуса, синхронизацией между устройствами и облачным хранилищем — 2-3 недели.







