Реалізація аннотування документів у мобільному застосунку
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. Для реалістичного рисування: змінюємо товщину лінії від сили натиснення, застосовуємо згладжування через алгоритм 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 тижні.







