Transition (анимација прелаза) — механизам визуелне смене једног садржаја другим: екрана, фрагмената, вјуова или стања интерфејса. Правилно имплементиран прелаз усмерава пажњу корисника, објашњава међусобну везу између елемената и чини навигацију интуитивном. Према Material Design Guidelines (2026), апликације са промишљеним прелазима показују 22% веће задржавање корисника у другој сесији. Више о другим врстама анимације прочитајте у општем водичу за анимацију.
Главно
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 API | Android 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 за прелаз од картице до детаљног екрана (картица производа → опис).
На iOS UIView.transition је најједноставнији начин анимације смене садржаја унутар једног View. Подржава cross-dissolve, curl-up, curl-down, flip-from-left, flip-from-right. За навигационе прелазе између UIViewController користи се UINavigationControllerDelegate са UIViewControllerAnimatedTransitioning — ово даје потпуну контролу над анимацијом push/pop.
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 — ово је стандардни образац за интерактивну навигацију.
На Android FragmentTransaction са setCustomAnimations је основни начин анимације прелаза између Fragment. Параметри: enter (анимација уласка новог Fragment), exit (анимација изласка старог), popEnter и popExit — за повратну навигацију. FragmentTransaction подржава анимације ресурса (R.anim) и Transition Framework (R.transition).
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 као fallback. Transition Framework не подржава SurfaceView, TextureView, GLSurfaceView — за видео и камеру користите само анимације кроз R.anim.
UIViewControllerAnimatedTransitioning — протокол iOS за креирање потпуно прилагођених анимација прелаза између контролера. Даје приступ контејнерском View (transitionContext.containerView), изворном и циљном View. У комбинацији са UIPercentDrivenInteractiveTransition овај приступ омогућава креирање интерактивних прелаза померањем прста.
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) — је декларативни систем анимације који аутоматски анимира промене између две сцене (Scene). Сцена је скуп View-ова са одређеним стањем. При прелазу са Scene A на Scene B, Transition Framework анализира разлику и анимира: промену позиције (ChangeBounds), промену величине (ChangeClipBounds, ChangeTransform), појављивање (Fade) и нестајање (Fade).
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).
Често постављана питања
Animation — анимација својстава једног објекта (alpha, translation, scale). Transition — анимација смене скупа објеката или стања (фрагмент → фрагмент, сцена → сцена). Transition управља вишеструким променама истовремено: појављивање, нестајање, премештање, промена величине — и аутоматски анимира разлику између два стања. Animation захтева ручно управљање сваким својством.
Користите 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 анимира само својства која не изазивају прерачун layout-а. За анимацију висине користите ChangeBounds — он аутоматски анимира промену граница View-а између два layout стања. Позовите TransitionManager.beginDelayedTransition(viewGroup, ChangeBounds()) пре промене LayoutParams. Ако се висина мења кроз WRAP_CONTENT, уверите се да је layout_height пре и после различит — ChangeBounds неће радити ако су оба стања match_parent.
Користите модификатор .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.
Користите 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.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође