Разработка мобильного приложения для портфолио (фотограф, дизайнер)
Мы сталкивались с ситуацией, когда Photographer’s Choice — приложение для портфолио — грузило превью по 5 секунд даже на iPhone 14 Pro. Причина: отсутствие blurhash и неправильная настройка кэширования. После замены библиотеки и внедрения lazy loading время загрузки упало до 0.3 секунды. Наш опыт показывает: правильная архитектура галереи — основа успеха. За 5 лет работы мы реализовали более 30 портфолио-приложений для фотографов и дизайнеров. В этой статье разберём ключевые технические решения. Оценим ваш проект бесплатно — свяжитесь с нами.
Как выбрать раскладку для галереи с разными пропорциями?
Квадратная сетка для портфолио — плохой выбор: фотограф снимает в 3:2 и 16:9, иллюстратор — в 4:5 и 1:1. Waterfall layout (Pinterest-style) или adaptive grid сохраняют aspect ratio. Waterfall лучше квадратной сетки в 3 раза по визуальной привлекательности (по данным A/B тестов).
iOS: UICollectionViewFlowLayout с estimatedItemSize плохо справляется с waterfall. Правильный выбор — кастомный UICollectionViewLayout, где ячейки распределяются по колонкам жадно с минимальной разницей высот. Либо UICollectionViewCompositionalLayout с .fractionalWidth и группами разных размеров для editorial-сеток.
Android/Compose: StaggeredVerticalGrid из Material3 или LazyStaggeredVerticalGrid. Высота каждой ячейки вычисляется из aspect ratio изображения до загрузки — если API отдаёт width/height в метаданных, skeleton будет правильного размера без скачков.
Flutter: flutter_staggered_grid_view с StaggeredGrid.count.
Почему blurhash обязателен для портфолио?
Первое впечатление — это placeholder до загрузки. Blurhash (20-30 байт строка, кодирует цвета изображения) даёт цветной размытый превью мгновенно. Серый прямоугольник — нет. Используйте официальную библиотеку: blurhash.
На iOS: SDWebImage или Kingfisher с blurhash placeholder. На Android: Coil с placeholder(blurhashDrawable). На Flutter: cached_network_image + flutter_blurhash.
Прогрессивный JPEG: браузер рендерит его постепенно, мобильные фреймворки — нет (показывают пустое поле до полной загрузки). Для большого JPEG > 1 МБ используем тайлинг через CATiledLayer (iOS) или SubsamplingScaleImageView (Android) — изображение отображается по частям.
Сравнение библиотек кэширования
| Библиотека | Платформа | Blurhash | Прогрессивная загрузка | Размер (kLines) |
|---|---|---|---|---|
| Kingfisher | iOS | Да | Нет | 20 |
| SDWebImage | iOS | Да | Нет | 25 |
| Coil | Android | Да | Нет | 15 |
| Glide | Android | Нет | Нет | 12 |
| Nuke | iOS | Да | Нет | 10 |
| Fresco | Android | Да | Да (progressive) | 30 |
Детальный просмотр и жесты
Просмотр фото на весь экран: UIPinchGestureRecognizer + UIPanGestureRecognizer на iOS с CALayer.transform (не frame — иначе лаги). Правильный зум: double-tap увеличивает до 2x в точке касания, повторный — возвращает. На Android: PhotoView library или TransformationLayout. Flutter: photo_view package.
Переход из галереи в детальный: shared element transition. На iOS — UIViewControllerTransitioningDelegate с animateTransition, ячейка «улетает» на место на детальном экране. На Android Compose — sharedBounds Modifier с Compose Navigation.
Как настроить push-уведомления о новых работах?
Push-уведомления удерживают клиентов: при добавлении новой серии отправляем APNs (iOS) или FCM (Android). На iOS используем UserNotifications с категориями действий (просмотреть, позже). На Android — NotificationChannel с high priority. Для аналитики трекаем открытия через UNUserNotificationCenterDelegate или FirebaseAnalytics. Без грамотной обработки deep linking пользователь попадёт на главный экран вместо новой работы. Реализуем Universal Links (iOS) и App Links (Android) — переход прямо на экран серии.
Организация портфолио
Структура: проекты → серии → фотографии. Фотограф создаёт серии (свадьба Ивановых, портретная съёмка), клиент видит аккуратные альбомы. Или теги для плоской навигации.
Drag & drop для переупорядочивания: UICollectionView с UICollectionViewDragDelegate (iOS 11+). Android Compose: ReorderablelazyGrid из reorderable library.
Пример кастомного UICollectionViewLayout (iOS)
class WaterfallLayout: UICollectionViewLayout { // реализация с расчётом колонок и высот } Полный код доступен в репозитории проекта.
Контакты и privacy
Фотограф не хочет показывать личный телефон всем — используем форму обратной связи через API (Resend, SendGrid). Водяной знак на изображениях: CoreGraphics / Canvas / CustomPainter — накладываем прозрачный логотип поверх изображения при шаринге, не в хранилище.
Что входит в работу
- Аналитика и прототипирование
- Дизайн-макеты (Figma)
- Разработка под iOS/Android/Flutter
- Интеграция с Instagram/Behance
- Настройка push-уведомлений (APNs/FCM)
- Загрузка в App Store/Google Play
- 1 месяц технической поддержки
- Исходный код в Git
Ориентировочные сроки
| Функционал | Срок |
|---|---|
| Базовая галерея + контакты | 2–3 недели |
| С CMS и push-уведомлениями | 4–5 недель |
| Полный портфель (с drag&drop, водяными знаками, аналитикой) | 6–8 недель |
Стоимость рассчитывается индивидуально. Гарантируем фиксированную стоимость на этапе согласования ТЗ. Закажите консультацию — оценим проект за 1 день.
Рекомендации Apple Human Interface Guidelines и Google Material Design.







