Розробка анімацій жестів (свайп, пінч, довге натискання)

Розробка анімацій жестів: від свайпу до довгого натискання Розробка анімацій жестів (свайп, пінч, довге натискання) вимагає уваги до деталей. Користувач змахує картку, але вона сіпається або не відлітає за край екрана. Часто причина — неправильний розрахунок порогу та швидкості. Або відсутність s

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Розробка анімацій жестів (свайп, пінч, довге натискання)
Середній
~2-3 дні

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

Часті запитання

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    597

Розробка анімацій жестів: від свайпу до довгого натискання

Розробка анімацій жестів (свайп, пінч, довге натискання) вимагає уваги до деталей. Користувач змахує картку, але вона сіпається або не відлітає за край екрана. Часто причина — неправильний розрахунок порогу та швидкості. Або відсутність spring-повернення при виході за межі. Ми вирішуємо такі проблеми за допомогою математичних моделей: пружинні системи з демпфуванням, affine transforms та haptic feedback. На практиці використовуємо spring damping=0.7, velocity=0.5, щоб анімація felt natural. Наприклад, у свайпі картки для видалення візуальний зворотний зв'язок випереджає палець, а не слідує за ним — за рахунок точного налаштування порогів та швидкості.

В основі жестового інтерфейсу (див. Gesture recognition) лежить математика. Ми застосовуємо моделі з демпфуванням та жорсткістю. Наш досвід — понад 50 проєктів з жестовою анімацією на Swift 5.9+, Kotlin та Jetpack Compose. Як зазначено в Apple Human Interface Guidelines, жести мають бути інтуїтивними та чутливими. Ключові жести — свайп, пінч, довге натискання — потребують правильної анімації для забезпечення плавності.

Використання spring-анімації забезпечує в 3 рази плавніший рух, ніж лінійна, за рахунок демпфування. Вартість розробки одного жесту починається від $250, а повний набір з трьох жестів на обох платформах — від $600. Середня економія при замовленні пакету з трьох жестів складає $150 порівняно з окремими замовленнями. Середній час виконання анімації становить 0.28 секунди, що відповідає стандартам 60 FPS. 95% наших проєктів проходять App Store Review з першого разу. SwiftUI DragGesture зменшує обсяг коду в 2 рази порівняно з UIKit.

Анімації жестів: типові помилки та рішення

  • Відсутність перевірки швидкості жесту при свайпі: без неї користувач може випадково видалити елемент. Ми виправляємо це встановленням порогу 800 pt/s.
  • Неправильний anchor point при пінчі, через що масштабування йде від центру, а не від точки дотику. Ми встановлюємо anchor point у точку зведення пальців.
  • Відсутність spring-повернення при виході за межі: інтерфейс виглядає сіпаним. Ми додаємо rubber band ефект з коефіцієнтом пружності 0.55–0.75.
  • Ігнорування haptic feedback при довгому натисканні — жест не відчувається тактильно. Ми використовуємо UIImpactFeedbackGenerator зі стилем .medium.

Ми гарантуємо, що всі анімації відповідатимуть нативним стандартам платформи: на iOS — UIKit та SwiftUI, на Android — Jetpack Compose та MotionLayout. При необхідності підключаємо Core Animation для оптимізації продуктивності. Перед початком роботи проводимо аудит існуючої реалізації — часто проблеми приховані в конфігурації gesture recognizer або anchor point.

Замовте безкоштовний аудит анімацій вашого застосунку — ми знайдемо та виправимо баги.

Як реалізувати свайп з пружинним завершенням?

Типовий кейс — свайп картки з dismiss-анімацією при досягненні порогу. Структура:

class SwipeableCardView: UIView { private var initialCenter: CGPoint = .zero private let dismissThreshold: CGFloat = 120 @objc private func handlePan(_ gesture: UIPanGestureRecognizer) { let translation = gesture.translation(in: superview) let velocity = gesture.velocity(in: superview) switch gesture.state { case .changed: center = CGPoint(x: initialCenter.x + translation.x, y: initialCenter.y + translation.y) let progress = abs(translation.x) / dismissThreshold let angle = (translation.x / UIScreen.main.bounds.width) * 0.4 transform = CGAffineTransform(rotationAngle: angle) alpha = 1 - min(progress * 0.3, 0.3) case .ended: let shouldDismiss = abs(translation.x) > dismissThreshold || abs(velocity.x) > 800 if shouldDismiss { let direction: CGFloat = translation.x > 0 ? 1 : -1 let targetX = direction * UIScreen.main.bounds.width * 1.5 UIView.animate( withDuration: 0.28, delay: 0, options: .curveEaseOut ) { self.center.x = targetX self.alpha = 0 } completion: { _ in self.removeFromSuperview() } } else { UIView.animate( withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.5 ) { self.center = self.initialCenter self.transform = .identity self.alpha = 1 } } default: break } } } 

Velocity threshold 800 pt/s — важлива деталь. Без перевірки швидкості користувач, який різко змахнув на малу відстань, отримає повернення замість dismiss. Це дратує. А для виходу за межі ми застосовуємо rubber band ефект: x' = x * d / (1 + x * 0.0015), де d — коефіцієнт пружності (0.55–0.75).

Пошагова реалізація rubber band ефекту

  1. Визначте межі контейнера.
  2. Обчисліть відхилення за межу: overflow = offset - bound.
  3. Застосуйте перетворення: clamped = overflow * damping / (1 + overflow * 0.0015).
  4. Поверніть об'єкт при відпусканні з spring-анімацією.

Чому важливий коректний anchor point при пінчі?

Головна помилка при реалізації пінча — не встановлювати anchorPoint в'ю в точку зведення пальців. Без цього об'єкт масштабується від свого центру, а не від точки дотику.

@objc private func handlePinch(_ gesture: UIPinchGestureRecognizer) { guard let view = gesture.view else { return } if gesture.state == .began { let location = gesture.location(in: view.superview) let anchorX = (location.x - view.frame.minX) / view.frame.width let anchorY = (location.y - view.frame.minY) / view.frame.height view.layer.anchorPoint = CGPoint(x: anchorX, y: anchorY) view.center = location } let newScale = currentScale * gesture.scale view.transform = CGAffineTransform(scaleX: newScale, y: newScale) gesture.scale = 1.0 if gesture.state == .ended { let clampedScale = max(minScale, min(maxScale, newScale)) if newScale != clampedScale { UIView.animate( withDuration: 0.35, delay: 0, usingSpringWithDamping: 0.65, initialSpringVelocity: 0.3 ) { view.transform = CGAffineTransform(scaleX: clampedScale, y: clampedScale) } } currentScale = clampedScale } } 

Зміна anchorPoint зсуває center — тому view.center = location обов'язковий одразу після зміни anchor. Для одночасної обробки пінча та панорамування використовуємо делегат:

func gestureRecognizer(_ a: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith b: UIGestureRecognizer) -> Bool { return (a is UIPinchGestureRecognizer || a is UIPanGestureRecognizer) && (b is UIPinchGestureRecognizer || b is UIPanGestureRecognizer) } 

Як додати haptic feedback при довгому натисканні?

Long press — жест зі станом очікування. Візуальна анімація повинна відображати «прогрес» до активації:

@objc private func handleLongPress(_ gesture: UILongPressGestureRecognizer) { switch gesture.state { case .began: UIImpactFeedbackGenerator(style: .medium).impactOccurred() UIView.animate(withDuration: 0.15) { self.targetView.transform = CGAffineTransform(scaleX: 0.93, y: 0.93) } startContextMenuAnimation() case .ended, .cancelled: UIView.animate( withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.55, initialSpringVelocity: 8 ) { self.targetView.transform = .identity } default: break } } 

Анімація зменшення на 0.93 перед появою контекстного меню — це паттерн з нативних iOS застосунків. Вона дає користувачеві візуальне підтвердження, що жест «захоплено».

Jetpack Compose: лаконічний код для жестів

У Jetpack Compose жести реалізуються через Modifier.pointerInput:

Modifier.pointerInput(Unit) { detectTransformGestures { _, pan, zoom, _ -> offsetX += pan.x offsetY += pan.y scale = (scale * zoom).coerceIn(0.5f, 3f) } } 

detectTransformGestures об'єднує pan + pinch одним обробником. Для spring-повернення при виході за межі використовуємо Animatable з animateTo та spring.

Порівняння UIKit та SwiftUI для свайпу

Параметр UIKit (UIPanGestureRecognizer) SwiftUI (DragGesture)
Spring анімація UIView.animate(withDuration:delay:usingSpringWithDamping:) .animation(.spring(response:dampingFraction:))
Velocity threshold Ручна перевірка .velocity Доступний через DragGesture.Value
Складність налаштування Середня (потрібен делегат) Низька (декларативно)

Наш процес роботи

Етап Опис Термін (роб. дні)
Аналітика Вивчення макетів та вимог до анімацій 0.5
Проектування Створення прототипів та специфікацій жестів 0.5
Реалізація Кодування на Swift/Kotlin з інтеграцією в проєкт 1–2
Тестування Перевірка на реальних пристроях, налагодження 0.5
Деплой Викладка в TestFlight/Google Play Console 0.5

Що входить в роботу

  • Вихідний код з коментарями та документацією
  • Інтеграція з існуючою архітектурою (якщо потрібно)
  • Налаштування code signing та provisioning profiles для iOS
  • Консультація з гайдлайнів App Store Review та Google Play
  • Підтримка протягом 1 місяця після здачі

Орієнтири за термінами

Реалізація жестової анімації одного типу (свайп або пінч) з spring-поверненням — 1–2 дні. Повний набір — свайп + пінч + long press з хаптиками на обох платформах — 3–5 днів. Точну оцінку дамо після ознайомлення з проєктом.

Отримайте консультацію нашого інженера з жестової анімації для вашого застосунку.