Transition: основи, анимация на преходи в мобилни приложения

Автор: IT Sectr Публикувано: 2026-03-02 Време за четене: 11 мин

Transition (анимация на преход) — механизъм за визуална смяна на едно съдържание с друго: екрани, фрагменти, изгледи или състояния на интерфейса. Правилно имплементираният преход насочва вниманието на потребителя, обяснява взаимовръзката между елементите и прави навигацията интуитивна. Според Material Design Guidelines (2026), приложенията с добре обмислени преходи показват 22% по-високо задържане на потребителите във втора сесия. Научете повече за други видове анимация в общото ръководство за анимация.

Основни точки

  • Transition — анимация на смяна на съдържание между екрани, фрагменти или състояния.
  • UIView.transition — основното API за анимация на преходи в iOS (UIKit).
  • FragmentTransaction.setCustomAnimations — настройка на анимация на преходи между Fragment в Android.
  • Transition Framework (android.transition) — декларативна система за анимация в Android за преход сцена към сцена.
  • UIViewControllerAnimatedTransitioning — протокол на iOS за персонализирани преходи между контролери.

Какво е Transition?

Transition — е анимация, която се случва при замяна на едно визуално състояние на интерфейса с друго. За разлика от Property Animation (анимация на свойство на един обект), Transition управлява цял набор от промени: появяване/изчезване на елементи, промяна на тяхната позиция, размер и свойства в рамките на един преход. Transition решава проблема с плавната смяна на съдържание, така че потребителят да разбира какво къде се е преместило.

На мобилни платформи Transition се прилага в три основни сценария: навигация между екрани (push, pop, modal present), смяна на фрагменти (Android FragmentTransaction) и промяна на състояние в рамките на екран (разгъване на карта, превключване на раздели). Всеки сценарий изисква свой подход: навигационни преходи — UIViewControllerAnimatedTransitioning в iOS или ActivityOptions в Android, вътрешноекранни преходи — Transition Framework или UIView.transition.

Според Apple HIG (2026), продължителността на стандартен преход не трябва да надвишава 400–500 ms — по-дългите анимации се възприемат като забавяне. Material Design препоръчва 300–350 ms за мобилни преходи. За големи елементи (карти, изображения) времето може да се увеличи до 500–600 ms без загуба на възприемана производителност.

Видове анимации на преходи

Видове преходи се разделят на няколко категории в зависимост от това кое съдържание се променя и как. Основни типове: избледняване (cross-fade) — плавно изчезване на едно и появяване на друго; плъзгане (slide) — един екран отива, друг идва; мащабиране (scale/zoom) — елемент се увеличава, отваряйки детайлен екран. Комбинираните преходи съчетават множество ефекти.

Тип преходОписаниеiOS APIAndroid API
Cross-fadeИзбледняване: едно съдържание изчезва, друго се появяваUIView.transition(with:duration:options:.transitionCrossDissolve)TransitionSet + Fade()
SlideПлъзгане: съдържание отива/идва хоризонтално или вертикалноCATransition(type: .push, subtype: .fromLeft)Slide() / FragmentTransaction.setCustomAnimations
Scale / ZoomМащабиране: елемент се увеличава на цял екранUIViewPropertyAnimator с scale анимацияScale() + ActivityOptions.makeScaleUpAnimation
ExplodeЕксплозия: съдържанието се разлита на части при изчезванеCATransition(type: .reveal)Explode() (API 21+)
Fade-throughИзбледняване през бял/черен екранUIView.transition(with: .transitionCrossDissolve, с бял фон)Fade() чрез ChangeBounds

Правила на Material Design: използвайте един тип преход в рамките на едно приложение за създаване на единен визуален език. Slide се препоръчва за навигация между екрани от едно ниво (master → detail), cross-fade за смяна на съдържание в рамките на един екран (раздели, превключване на изглед), scale/zoom за преход от карта към детайлен екран (карта на продукт → описание).

Transition в iOS (Swift)

В iOS UIView.transition е най-простият начин за анимиране на смяна на съдържание в рамките на един View. Поддържа cross-dissolve, curl-up, curl-down, flip-from-left, flip-from-right. За навигационни преходи между UIViewController се използва UINavigationControllerDelegate с UIViewControllerAnimatedTransitioning — това дава пълен контрол върху push/pop анимацията.

swift
import UIKit

// UIView.transition: смяна на изображение с cross-dissolve
UIView.transition(with: imageView,
    duration: 0.4,
    options: [.transitionCrossDissolve, .curveEaseInOut]
) {
    self.imageView.image = UIImage(named: "new_image")
} completion: { _ in
    print("Transition завършен")
}

// UIView.transition: смяна на два View
UIView.transition(from: firstView, to: secondView,
    duration: 0.5,
    options: [.transitionFlipFromRight, .showHideTransitionViews]
) { _ in
    // firstView скрит, secondView показан
}

// CATransition за слой (без Auto Layout)
let transition = CATransition()
transition.type = .push
transition.subtype = .fromRight
transition.duration = 0.35
transition.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
view.layer.add(transition, forKey: "pushTransition")

UIViewPropertyAnimator — модерна алтернатива за персонализирани преходи в iOS 10+. За разлика от UIView.transition, PropertyAnimator поддържа пауза, отказ и reverse (обратна анимация), което е важно за интерактивни преходи (swipe-to-go-back). За анимация между UIViewController използвайте UIPercentDrivenInteractiveTransition в комбинация с PropertyAnimator — това е стандартният модел за интерактивна навигация.

Transition в Android (Kotlin)

В Android FragmentTransaction с setCustomAnimations е основният начин за анимиране на преходи между Fragment. Параметри: enter (анимация на влизане на нов Fragment), exit (анимация на излизане на стар), popEnter и popExit — за обратна навигация. FragmentTransaction поддържа ресурсни анимации (R.anim) и Transition Framework (R.transition).

kotlin
import androidx.fragment.app.FragmentTransaction
import androidx.transition.TransitionInflater

// FragmentTransaction с ресурсни анимации
supportFragmentManager.beginTransaction()
    .setCustomAnimations(
        R.anim.slide_in_right,  // enter
        R.anim.slide_out_left,  // exit
        R.anim.slide_in_left,   // popEnter
        R.anim.slide_out_right  // popExit
    )
    .replace(R.id.container, DetailFragment())
    .addToBackStack(null)
    .commit()

// FragmentTransaction с Transition Framework
val detailFragment = DetailFragment()
detailFragment.enterTransition = TransitionInflater.from(this)
    .inflateTransition(R.transition.slide_right)
detailFragment.exitTransition = TransitionInflater.from(this)
    .inflateTransition(R.transition.fade_out)

supportFragmentManager.beginTransaction()
    .replace(R.id.container, detailFragment)
    .addToBackStack(null)
    .commit()

// ActivityOptions: анимация при стартиране на Activity
val options = ActivityOptions.makeScaleUpAnimation(
    view, 0, 0, view.width, view.height
).toBundle()
startActivity(intent, options)

Най-добри практики за Android: Slide() — за замяна на Fragment в навигация (enter = Slide(Gravity.END), exit = Slide(Gravity.START)). Fade() — за показване/скриване на overlay и диалози. Explode() — за акцентирани преходи (премахване на елемент от списък). За стари устройства (API < 21) използвайте R.anim като резервен вариант. Transition Framework не поддържа SurfaceView, TextureView, GLSurfaceView — за видео и камера използвайте само анимации чрез R.anim.

Персонализирани преходи UIViewController в iOS

UIViewControllerAnimatedTransitioning — протокол на iOS за създаване на напълно персонализирани анимации на преход между контролери. Предоставя достъп до контейнерния View (transitionContext.containerView), изходния и целевия View. В комбинация с UIPercentDrivenInteractiveTransition този подход позволява създаване на интерактивни преходи с плъзгане с пръст.

swift
import UIKit

"> Кастомный аниматор перехода
class ScaleTransitionAnimator: NSObject, UIViewControllerAnimatedTransitioning {
    let isPresenting: Bool

    init(presenting: Bool) { self.isPresenting = presenting }

    func transitionDuration(using ctx: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.4
    }

    func animateTransition(using ctx: UIViewControllerContextTransitioning) {
        guard let toView = ctx.view(forKey: .to),
              let fromView = ctx.view(forKey: .from)
        else { return }

        let container = ctx.containerView
        let initialScale: CGAffineTransform = CGAffineTransform(scaleX: 0.8, y: 0.8)
        let finalFrame = ctx.finalFrame(for: toView)

        if isPresenting {
            toView.transform = initialScale
            toView.alpha = 0
            toView.frame = finalFrame
            container.addSubview(toView)
        }

        UIView.animate(withDuration: transitionDuration(using: ctx),
                       delay: 0,
                       usingSpringWithDamping: 0.7,
                       initialSpringVelocity: 0.3) {
            if self.isPresenting {
                toView.transform = .identity
                toView.alpha = 1
                fromView.transform = CGAffineTransform(scaleX: 0.9, y: 0.9)
                fromView.alpha = 0
            } else {
                fromView.transform = initialScale
                fromView.alpha = 0
            }
        } completion: { _ in
            fromView.transform = .identity
            ctx.completeTransition(!ctx.transitionWasCancelled)
        }
    }
}

// Приложение в UINavigationControllerDelegate
extension MainViewController: UINavigationControllerDelegate {
    func navigationController(
        _ nc: UINavigationController,
        animationControllerFor operation: UINavigationController.Operation,
        from: UIViewController, to: UIViewController
    ) -> UIViewControllerAnimatedTransitioning? {
        return ScaleTransitionAnimator(presenting: operation == .push)
    }
}

Интерактивни преходи: добавете UIPanGestureRecognizer към изходния екран. При задействане на жеста създайте UIPercentDrivenInteractiveTransition и извикайте update(CGFloat(percent)). За отмяна при недостигане на прага (обикновено 30%) извикайте cancel(). Този модел се използва по подразбиране в UINavigationController при pop жест и в UIScrollView с pagingEnabled. За персонализирани жестове имплементирайте UIViewControllerInteractiveTransitioning.

Transition Framework в Android: сцена към сцена

Transition Framework (android.transition) — е декларативна система за анимация, която автоматично анимира промените между две сцени (Scene). Сцена е набор от View с определено състояние. При преход от Scene A към Scene B, Transition Framework анализира разликата и анимира: промяна на позиция (ChangeBounds), промяна на размер (ChangeClipBounds, ChangeTransform), появяване (Fade) и изчезване (Fade).

kotlin
import android.transition.Scene
import android.transition.TransitionManager
import android.transition.TransitionSet
import android.transition.AutoTransition
import android.transition.ChangeBounds
import android.transition.Fade

// TransitionSet: комбинация ChangeBounds + Fade
val transition = TransitionSet().apply {
    ordering = TransitionSet.ORDERING_TOGETHER
    addTransition(ChangeBounds())
    addTransition(Fade(Fade.IN))
    duration = 400L
    interpolator = FastOutSlowInInterpolator()
}

// Преход между сцени в ViewGroup
val sceneRoot = findViewById<ViewGroup>(R.id.scene_root)
val scene1 = Scene.getSceneForLayout(sceneRoot, R.layout.scene_initial)
val scene2 = Scene.getSceneForLayout(sceneRoot, R.layout.scene_expanded)

"> AutoTransition без ручной настройки
TransitionManager.go(scene2, AutoTransition().apply {
    duration = 350L
})

// TransitionManager.beginDelayedTransition — без сцени
TransitionManager.beginDelayedTransition(sceneRoot, ChangeBounds())
itemView.layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT
itemView.requestLayout() "> Изменение layout анимируется автоматически

ChangeBounds — най-често използваният преход в Android, анимира промяна на позиция и размер на View. ChangeTransform анимира rotation и scale. ChangeImageTransform — за анимация на ImageView (centerCrop → fitCenter). За сложни преходи с промяна на йерархичната структура използвайте TransitionSet с ordering = ORDERING_SEQUENTIAL (анимациите се изпълняват последователно, а не паралелно). Според документацията на Android Developers (2026), Transition Framework поддържа всички стандартни View, но не поддържа анимация на повърхност (SurfaceView, TextureView, VideoView).

Често задавани въпроси

Каква е разликата между Transition и Animation?

Animation — анимация на свойствата на един обект (alpha, translation, scale). Transition — анимация на промяна на набор от обекти или състояния (фрагмент → фрагмент, сцена → сцена). Transition управлява множество промени едновременно: появяване, изчезване, преместване, промяна на размер — и автоматично анимира разликата между две състояния. Animation изисква ръчно управление на всяко свойство.

Как да направим плавен преход между фрагменти в Android?

Използвайте FragmentTransaction.setCustomAnimations с Transition Framework: fragment1.exitTransition = Fade(Fade.OUT), fragment2.enterTransition = Slide(Gravity.END). За последователност: setReorderingAllowed(true) — фрагментите ще бъдат пренаредени за плавен паралелен преход. За прости случаи са достатъчни slide_in_right / slide_out_left от R.anim. За обратна навигация задайте popEnter и popExit.

Transition Framework не анимира промяна на височината на View — какво да правим?

Transition Framework анимира само свойства, които не предизвикват преизчисляване на layout-а. За анимация на височина използвайте ChangeBounds — той автоматично анимира промяна на границите на View между две layout състояния. Извикайте TransitionManager.beginDelayedTransition(viewGroup, ChangeBounds()) преди промяна на LayoutParams. Ако височината се променя чрез WRAP_CONTENT, уверете се, че layout_height преди и след е различен — ChangeBounds няма да работи, ако и двете състояния са match_parent.

Как да направим персонализиран преход в SwiftUI?

Използвайте модификатора .transition() с AnyTransition: .transition(.move(edge: .trailing).combined(with: .opacity)). За персонализирани преходи имплементирайте AnyTransition.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)). За анимация в NavigationStack използвайте .navigationTransition(.slide) в iOS 18+. SwiftUI не поддържа UIViewControllerAnimatedTransitioning — само декларативни преходи чрез AnyTransition.

Как да измерим производителността на Transition?

Използвайте Profile GPU Rendering (Android) или Core Animation Instrument (iOS). За Android добавете профилиране на Transition чрез adb shell setprop debug.transition.profiling 1 — в логовете ще се появят продължителностите на всеки етап от прехода. На iOS включете Slow Animations в симулатора. Целеви метрики: продължителност < 400 ms, FPS >= 55, frame drops — не повече от 2 на преход. За сложни сцени с 15+ едновременно анимирани View използвайте ChangeBounds с duration 300 ms.

Резюме

  • Transition — анимация на смяна на съдържание между екрани, фрагменти или състояния на интерфейса.
  • UIView.transition (iOS) — основно API за cross-dissolve, flip, curl преходи в рамките на View.
  • UIViewControllerAnimatedTransitioning (iOS) — протокол за персонализирани преходи между контролери.
  • FragmentTransaction.setCustomAnimations (Android) — анимация на преходи между Fragment.
  • Transition Framework (android.transition) — декларативна система за сцени: ChangeBounds, Fade, Slide, Explode.
  • Препоръчителна продължителност: 300–400 ms за мобилни устройства, до 600 ms за големи елементи.
  • Един тип преход на приложение за единен визуален език (Material Design).

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също