Реализация анимаций Hero-переходов между экранами мобильного приложения

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1735 услуг
Реализация анимаций Hero-переходов между экранами мобильного приложения
Средний
от 1 дня до 3 дней
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    495

Реализация анимаций Hero-переходов между экранами мобильного приложения

Hero-переход — когда элемент с одного экрана «летит» на другой экран, становясь его частью. Карточка товара раскрывается в полноэкранный детальный вид, аватар из списка плавно перемещается в шапку профиля. Пользователь понимает пространственную связь между экранами без объяснений.

Сложность не в самой анимации — в правильной синхронизации lifecycle двух экранов, чтобы элемент выглядел непрерывно движущимся, а не исчезающим на одном экране и появляющимся на другом.

Flutter: Hero widget

Flutter реализует hero-переходы нативно через виджет Hero:

// Экран со списком
Hero(
  tag: 'product-image-${product.id}',  // уникальный тег
  child: CachedNetworkImage(
    imageUrl: product.imageUrl,
    fit: BoxFit.cover,
  ),
)

// Экран деталей
Hero(
  tag: 'product-image-${product.id}',
  child: CachedNetworkImage(
    imageUrl: product.imageUrl,
    fit: BoxFit.contain,
  ),
)

Navigator.push с любым PageRoute автоматически запустит hero-анимацию между Hero виджетами с одинаковым tag. Продолжительность — 300 мс по умолчанию, контролируется через transitionDuration в MaterialPageRoute или кастомном PageRoute.

Проблемы: если изображение в списке обрезается ClipRRect, а на экране деталей нет — во время перехода форма скачет. Решение: Hero c flightShuttleBuilder для кастомного виджета во время полёта:

Hero(
  tag: 'product-image-${product.id}',
  flightShuttleBuilder: (_, animation, __, fromCtx, toCtx) {
    return AnimatedBuilder(
      animation: animation,
      builder: (_, child) => ClipRRect(
        borderRadius: BorderRadius.lerp(
          BorderRadius.circular(12),
          BorderRadius.zero,
          animation.value,
        )!,
        child: child,
      ),
      child: CachedNetworkImage(imageUrl: product.imageUrl, fit: BoxFit.cover),
    );
  },
  child: ...,
)

Это анимирует borderRadius от 12 (карточка) до 0 (полный экран) во время перехода.

React Native: Shared Element Transition

В React Native нет нативного hero-перехода. Используем react-native-shared-element (реального нативного уровня) или react-navigation v6 с createSharedElementStackNavigator от react-navigation-shared-element:

// Список
<SharedElement id={`product.${item.id}.image`}>
  <Image source={{ uri: item.imageUrl }} style={styles.thumbnail} />
</SharedElement>

// Детальный экран
<SharedElement id={`product.${item.id}.image`}>
  <Image source={{ uri: item.imageUrl }} style={styles.fullImage} />
</SharedElement>

Конфигурация навигатора:

const Stack = createSharedElementStackNavigator();

<Stack.Screen
  name="ProductDetail"
  component={ProductDetailScreen}
  sharedElements={(route) => [
    { id: `product.${route.params.product.id}.image`, animation: 'move' },
    { id: `product.${route.params.product.id}.title`, animation: 'fade' },
  ]}
/>

animation: 'move' — элемент перемещается. 'fade' — cross-fade на месте. 'fade-in' — появляется на новом месте. Для изображений — 'move', для текста — 'fade' (текст разного размера некрасиво масштабируется).

iOS (SwiftUI): matchedGeometryEffect

@Namespace private var heroNamespace

// В списке
Image(product.imageName)
    .matchedGeometryEffect(id: "product-image-\(product.id)", in: heroNamespace)
    .frame(width: 80, height: 80)

// В детальном виде (conditional rendering)
if showDetail {
    Image(product.imageName)
        .matchedGeometryEffect(id: "product-image-\(product.id)", in: heroNamespace)
        .frame(width: UIScreen.main.bounds.width, height: 300)
}

matchedGeometryEffect работает внутри одного View-иерархии. Для модальных экранов (sheet, fullScreenCover) — сложнее, требует кастомного перехода через AnyTransition с GeometryEffect. Подробнее — см. услугу по Matched Geometry Effect.

Типичные проблемы

Мерцание в начале перехода: элемент на исходном экране мгновенно исчезает при старте анимации. В Flutter — Hero по умолчанию скрывает оригинал через Opacity, это нормально. В React Native — SharedElement иногда показывает оба элемента одновременно. Исправляется через useNativeDriver: true и проверкой версий библиотеки.

Разное содержимое: изображение в списке — cached thumbnail, на детальном экране — оригинал в высоком разрешении. Пока грузится оригинал, hero должен показывать thumbnail. В Flutter — Hero всегда использует виджет из исходного экрана во время полёта, потом переключается. Убедитесь, что CachedNetworkImage на обоих экранах использует один и тот же URL для одинакового размера, или явно указывайте memCacheWidth.

Сроки

Hero-переход для одного типа элемента (изображение или карточка) на одной платформе: 1 день. Несколько типов hero-элементов (изображение + текст + иконка) с кастомной анимацией формы: 2–3 дня. Стоимость рассчитывается индивидуально.