Transition (animační přechod) — mechanismus vizuální změny jednoho obsahu na jiný: obrazovek, fragmentů, view nebo stavů rozhraní. Správně implementovaný přechod směruje pozornost uživatele, vysvětluje vztah mezi prvky a činí navigaci intuitivní. Podle Material Design Guidelines (2026) vykazují aplikace s promyšlenými přechody o 22 % vyšší udržení uživatelů ve druhé relaci. Více o dalších typech animací si přečtěte v obecném průvodci animacemi.
Hlavní body
Transition — je animace, ke které dochází při nahrazení jednoho vizuálního stavu rozhraní jiným. Na rozdíl od Property Animation (animace vlastnosti jednoho objektu) Transition spravuje celou sadu změn: objevování/mizení prvků, změnu jejich pozice, velikosti a vlastností v rámci jednoho přechodu. Transition řeší problém plynulé změny obsahu tak, aby uživatel chápal, co se kam přesunulo.
Na mobilních platformách se Transition uplatňuje ve třech hlavních scénářích: navigace mezi obrazovkami (push, pop, modal present), změna fragmentů (Android FragmentTransaction) a změna stavu uvnitř obrazovky (rozbalení karty, přepínání karet). Každý scénář vyžaduje svůj přístup: navigační přechody — UIViewControllerAnimatedTransitioning v iOS nebo ActivityOptions v Android, vnitroobrazovkové přechody — Transition Framework nebo UIView.transition.
Podle Apple HIG (2026) by doba trvání standardního přechodu neměla přesáhnout 400–500 ms — delší animace jsou vnímány jako zpoždění. Material Design doporučuje 300–350 ms pro mobilní přechody. U velkých prvků (karty, obrázky) se může čas zvýšit až na 500–600 ms bez ztráty vnímaného výkonu.
Typy přechodů se dělí do několika kategorií v závislosti na tom, jaký obsah se mění a jak. Základní typy: prolínání (cross-fade) — plynulé mizení jednoho a objevení druhého; posuv (slide) — jedna obrazovka odjíždí, druhá přijíždí; škálování (scale/zoom) — prvek se zvětší a otevře detailní obrazovku. Kombinované přechody spojují několik efektů.
| Typ přechodu | Popis | iOS API | Android API |
|---|---|---|---|
| Cross-fade | Prolínání: jeden obsah mizí, druhý se objevuje | UIView.transition(with:duration:options:.transitionCrossDissolve) | TransitionSet + Fade() |
| Slide | Posuv: obsah odjíždí/přijíždí horizontálně nebo vertikálně | CATransition(type: .push, subtype: .fromLeft) | Slide() / FragmentTransaction.setCustomAnimations |
| Scale / Zoom | Škálování: prvek se zvětší na celou obrazovku | UIViewPropertyAnimator s animací scale | Scale() + ActivityOptions.makeScaleUpAnimation |
| Explode | Exploze: obsah se při mizení rozletí na kusy | CATransition(type: .reveal) | Explode() (API 21+) |
| Fade-through | Prolínání přes bílou/černou obrazovku | UIView.transition(with: .transitionCrossDissolve, s bílým pozadím) | Fade() přes ChangeBounds |
Pravidla Material Design: používejte jeden typ přechodu v rámci jedné aplikace pro vytvoření jednotného vizuálního jazyka. Slide se doporučuje pro navigaci mezi obrazovkami stejné úrovně (master → detail), cross-fade pro změnu obsahu v rámci jedné obrazovky (karty, přepínání zobrazení), scale/zoom pro přechod z karty na detailní obrazovku (karta produktu → popis).
Na iOS je UIView.transition nejjednodušší způsob animace změny obsahu v rámci jednoho View. Podporuje cross-dissolve, curl-up, curl-down, flip-from-left, flip-from-right. Pro navigační přechody mezi UIViewController se používá UINavigationControllerDelegate s UIViewControllerAnimatedTransitioning — to poskytuje plnou kontrolu nad animací push/pop.
import UIKit
// UIView.transition: změna obrázku s cross-dissolve
UIView.transition(with: imageView,
duration: 0.4,
options: [.transitionCrossDissolve, .curveEaseInOut]
) {
self.imageView.image = UIImage(named: "new_image")
} completion: { _ in
print("Transition dokončen")
}
// UIView.transition: změna dvou View
UIView.transition(from: firstView, to: secondView,
duration: 0.5,
options: [.transitionFlipFromRight, .showHideTransitionViews]
) { _ in
// firstView skrytý, secondView zobrazený
}
// CATransition pro vrstvu (bez 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 — moderní alternativa pro vlastní přechody na iOS 10+. Na rozdíl od UIView.transition podporuje PropertyAnimator pozastavení, zrušení a reverse (obrácenou animaci), což je důležité pro interaktivní přechody (swipe-to-go-back). Pro animaci mezi UIViewController použijte UIPercentDrivenInteractiveTransition v kombinaci s PropertyAnimator — to je standardní vzor pro interaktivní navigaci.
Na Android je FragmentTransaction s setCustomAnimations hlavním způsobem animace přechodů mezi Fragment. Parametry: enter (animace vstupu nového Fragment), exit (animace výstupu starého), popEnter a popExit — pro zpětnou navigaci. FragmentTransaction podporuje animace zdrojů (R.anim) a Transition Framework (R.transition).
import androidx.fragment.app.FragmentTransaction
import androidx.transition.TransitionInflater
// FragmentTransaction s animacemi zdrojů
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 s 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: animace při spuštění Activity
val options = ActivityOptions.makeScaleUpAnimation(
view, 0, 0, view.width, view.height
).toBundle()
startActivity(intent, options)
Nejlepší postupy Android: Slide() — pro nahrazení Fragment v navigaci (enter = Slide(Gravity.END), exit = Slide(Gravity.START)). Fade() — pro zobrazení/skrytí překryvů a dialogů. Explode() — pro zvýrazněné přechody (odstranění prvku ze seznamu). Pro starší zařízení (API < 21) použijte R.anim jako záložní řešení. Transition Framework nepodporuje SurfaceView, TextureView, GLSurfaceView — pro video a kameru používejte pouze animace přes R.anim.
UIViewControllerAnimatedTransitioning — protokol iOS pro vytváření zcela vlastních animací přechodu mezi ovladači. Poskytuje přístup k View kontejneru (transitionContext.containerView), zdrojovému a cílovému View. V kombinaci s UIPercentDrivenInteractiveTransition tento přístup umožňuje vytvářet interaktivní přechody tažením prstem.
import UIKit
"> Vlastní animátor přechodu
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)
}
}
}
// Použití v UINavigationControllerDelegate
extension MainViewController: UINavigationControllerDelegate {
func navigationController(
_ nc: UINavigationController,
animationControllerFor operation: UINavigationController.Operation,
from: UIViewController, to: UIViewController
) -> UIViewControllerAnimatedTransitioning? {
return ScaleTransitionAnimator(presenting: operation == .push)
}
}
Interaktivní přechody: přidejte UIPanGestureRecognizer na zdrojovou obrazovku. Při aktivaci gesta vytvořte UIPercentDrivenInteractiveTransition a zavolejte update(CGFloat(percent)). Pro zrušení při nedosažení prahu (obvykle 30 %) zavolejte cancel(). Tento vzor se standardně používá v UINavigationController při pop gestu a v UIScrollView s pagingEnabled. Pro vlastní gesta implementujte UIViewControllerInteractiveTransitioning.
Transition Framework (android.transition) — je deklarativní systém animace, který automaticky animuje změny mezi dvěma scénami (Scene). Scéna je sada View s určitým stavem. Při přechodu ze Scene A na Scene B Transition Framework analyzuje rozdíl a animuje: změnu pozice (ChangeBounds), změnu velikosti (ChangeClipBounds, ChangeTransform), objevení (Fade) a zmizení (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: kombinace ChangeBounds + Fade
val transition = TransitionSet().apply {
ordering = TransitionSet.ORDERING_TOGETHER
addTransition(ChangeBounds())
addTransition(Fade(Fade.IN))
duration = 400L
interpolator = FastOutSlowInInterpolator()
}
// Přechod mezi scénami v 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 bez ruční konfigurace
TransitionManager.go(scene2, AutoTransition().apply {
duration = 350L
})
// TransitionManager.beginDelayedTransition — bez scén
TransitionManager.beginDelayedTransition(sceneRoot, ChangeBounds())
itemView.layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT
itemView.requestLayout() "> Změna layoutu je animována automaticky
ChangeBounds — nejpoužívanější přechod v Android, animuje změnu polohy a velikosti View. ChangeTransform animuje rotation a scale. ChangeImageTransform — pro animaci ImageView (centerCrop → fitCenter). Pro složité přechody se změnou struktury hierarchie použijte TransitionSet s ordering = ORDERING_SEQUENTIAL (animace se provádějí postupně, ne paralelně). Podle dokumentace Android Developers (2026) Transition Framework podporuje všechna standardní View, ale nepodporuje animaci povrchu (SurfaceView, TextureView, VideoView).
Často kladené otázky
Animation — animace vlastností jednoho objektu (alpha, translation, scale). Transition — animace změny sady objektů nebo stavů (fragment → fragment, scéna → scéna). Transition spravuje více změn současně: objevení, zmizení, přesun, změnu velikosti — a automaticky animuje rozdíl mezi dvěma stavy. Animation vyžaduje ruční správu každé vlastnosti.
Použijte FragmentTransaction.setCustomAnimations s Transition Framework: fragment1.exitTransition = Fade(Fade.OUT), fragment2.enterTransition = Slide(Gravity.END). Pro sekvenci: setReorderingAllowed(true) — fragmenty budou přeuspořádány pro plynulý paralelní přechod. Pro jednoduché případy stačí slide_in_right / slide_out_left z R.anim. Pro zpětnou navigaci určete popEnter a popExit.
Transition Framework animuje pouze vlastnosti, které nezpůsobují přepočet layoutu. Pro animaci výšky použijte ChangeBounds — automaticky animuje změnu hranic View mezi dvěma stavy layoutu. Zavolejte TransitionManager.beginDelayedTransition(viewGroup, ChangeBounds()) před změnou LayoutParams. Pokud se výška mění přes WRAP_CONTENT, ujistěte se, že layout_height před a po je rozdílný — ChangeBounds nebude fungovat, pokud jsou oba stavy match_parent.
Použijte modifikátor .transition() s AnyTransition: .transition(.move(edge: .trailing).combined(with: .opacity)). Pro vlastní přechody implementujte AnyTransition.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)). Pro animaci uvnitř NavigationStack použijte .navigationTransition(.slide) v iOS 18+. SwiftUI nepodporuje UIViewControllerAnimatedTransitioning — pouze deklarativní přechody přes AnyTransition.
Použijte Profile GPU Rendering (Android) nebo Core Animation Instrument (iOS). Pro Android přidejte profilování Transition přes adb shell setprop debug.transition.profiling 1 — v logech se objeví doby trvání každé fáze přechodu. Na iOS zapněte Slow Animations v simulátoru. Cílové metriky: trvání < 400 ms, FPS >= 55, frame drops — ne více než 2 na přechod. Pro složité scény s 15+ současně animovanými View použijte ChangeBounds s duration 300 ms.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také