Transition (övergångsanimering) — mekanism för visuell växling av ett innehåll till ett annat: skärmar, fragment, vyer eller gränssnittstillstånd. En korrekt implementerad övergång styr användarens uppmärksamhet, förklarar sambandet mellan element och gör navigeringen intuitiv. Enligt Material Design Guidelines (2026) visar appar med genomtänkta övergångar 22 % högre användarbehållning vid den andra sessionen. Läs mer om andra animeringstyper i den allmänna guiden för animering.
Huvudpunkter
Transition — är en animering som inträffar när ett visuellt gränssnittstillstånd ersätts med ett annat. Till skillnad från Property Animation (animering av egenskaper hos ett objekt) hanterar Transition en hel uppsättning förändringar: synliggörande/döljande av element, ändring av deras position, storlek och egenskaper inom en enda övergång. Transition löser problemet med smidigt innehållsbyte så att användaren förstår vad som flyttades vart.
På mobila plattformar tillämpas Transition i tre huvudsakliga scenarier: navigering mellan skärmar (push, pop, modal present), växling av fragment (Android FragmentTransaction) och tillståndsändring inom en skärm (expandera kort, växla flikar). Varje scenario kräver sin egen metod: navigeringsövergångar — UIViewControllerAnimatedTransitioning i iOS eller ActivityOptions i Android, intra-skärmövergångar — Transition Framework eller UIView.transition.
Enligt Apple HIG (2026) bör varaktigheten för en standardövergång inte överstiga 400–500 ms — längre animeringar uppfattas som fördröjning. Material Design rekommenderar 300–350 ms för mobila övergångar. För stora element (kort, bilder) kan tiden ökas till 500–600 ms utan förlust av upplevd prestanda.
Övergångstyper delas in i flera kategorier beroende på vilket innehåll som ändras och hur. Grundtyper: toning (cross-fade) — gradvis försvinnande av en och uppträdande av en annan; glidning (slide) — en skärm åker iväg, en annan kommer in; skalning (scale/zoom) — ett element förstoras och öppnar en detaljerad skärm. Kombinerade övergångar blandar flera effekter.
| Övergångstyp | Beskrivning | iOS API | Android API |
|---|---|---|---|
| Cross-fade | Toning: ett innehåll försvinner, ett annat visas | UIView.transition(with:duration:options:.transitionCrossDissolve) | TransitionSet + Fade() |
| Slide | Glidning: innehåll åker iväg/kommer in horisontellt eller vertikalt | CATransition(type: .push, subtype: .fromLeft) | Slide() / FragmentTransaction.setCustomAnimations |
| Scale / Zoom | Skalning: element förstoras till helskärm | UIViewPropertyAnimator med scale-animering | Scale() + ActivityOptions.makeScaleUpAnimation |
| Explode | Explosion: innehåll splittras vid försvinnande | CATransition(type: .reveal) | Explode() (API 21+) |
| Fade-through | Toning genom vit/svart skärm | UIView.transition(with: .transitionCrossDissolve, med vit bakgrund) | Fade() genom ChangeBounds |
Material Design-regler: använd en övergångstyp inom en app för att skapa ett enhetligt visuellt språk. Slide rekommenderas för navigering mellan skärmar på samma nivå (master → detail), cross-fade för innehållsbyte inom en skärm (flikar, vyväxling), scale/zoom för övergång från kort till detaljerad skärm (produktkort → beskrivning).
På iOS är UIView.transition det enklaste sättet att animera innehållsbyte inom en enda View. Det stöder cross-dissolve, curl-up, curl-down, flip-from-left, flip-from-right. För navigeringsövergångar mellan UIViewController används UINavigationControllerDelegate med UIViewControllerAnimatedTransitioning — detta ger full kontroll över push/pop-animeringen.
import UIKit
// UIView.transition: bildbyte med cross-dissolve
UIView.transition(with: imageView,
duration: 0.4,
options: [.transitionCrossDissolve, .curveEaseInOut]
) {
self.imageView.image = UIImage(named: "new_image")
} completion: { _ in
print("Transition slutförd")
}
// UIView.transition: byte av två Vyer
UIView.transition(from: firstView, to: secondView,
duration: 0.5,
options: [.transitionFlipFromRight, .showHideTransitionViews]
) { _ in
// firstView dold, secondView visad
}
// CATransition för lager (utan 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 — ett modernt alternativ för anpassade övergångar på iOS 10+. Till skillnad från UIView.transition stöder PropertyAnimator paus, avbrytning och reverse (omvänd animering), vilket är viktigt för interaktiva övergångar (swipe-to-go-back). För animering mellan UIViewController, använd UIPercentDrivenInteractiveTransition tillsammans med PropertyAnimator — detta är standardmönstret för interaktiv navigering.
På Android är FragmentTransaction med setCustomAnimations det primära sättet att animera övergångar mellan Fragment. Parametrar: enter (animering för det nya Fragmentets inträde), exit (animering för det gamlas utträde), popEnter och popExit — för bakåtnavigering. FragmentTransaction stöder resursanimeringar (R.anim) och Transition Framework (R.transition).
import androidx.fragment.app.FragmentTransaction
import androidx.transition.TransitionInflater
// FragmentTransaction med resursanimeringar
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 med 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: animering vid start av Activity
val options = ActivityOptions.makeScaleUpAnimation(
view, 0, 0, view.width, view.height
).toBundle()
startActivity(intent, options)
Android bästa praxis: Slide() — för att ersätta Fragment i navigering (enter = Slide(Gravity.END), exit = Slide(Gravity.START)). Fade() — för att visa/dölja overlay och dialogrutor. Explode() — för accentuerade övergångar (borttagning av element från lista). För äldre enheter (API < 21) använd R.anim som reserv. Transition Framework stöder inte SurfaceView, TextureView, GLSurfaceView — för video och kamera, använd endast animeringar via R.anim.
UIViewControllerAnimatedTransitioning — iOS-protokoll för att skapa helt anpassade övergångsanimeringar mellan kontroller. Det ger tillgång till behållar-Vyn (transitionContext.containerView), käll- och mål-Vy. I kombination med UIPercentDrivenInteractiveTransition möjliggör detta tillvägagångssätt att skapa interaktiva övergångar med fingersvepning.
import UIKit
"> Anpassad övergångsanimator
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)
}
}
}
// Tillämpning i UINavigationControllerDelegate
extension MainViewController: UINavigationControllerDelegate {
func navigationController(
_ nc: UINavigationController,
animationControllerFor operation: UINavigationController.Operation,
from: UIViewController, to: UIViewController
) -> UIViewControllerAnimatedTransitioning? {
return ScaleTransitionAnimator(presenting: operation == .push)
}
}
Interaktiva övergångar: lägg till en UIPanGestureRecognizer på källskärmen. När gesten utlöses, skapa en UIPercentDrivenInteractiveTransition och anropa update(CGFloat(percent)). För avbrytning när tröskeln inte nås (vanligtvis 30%), anropa cancel(). Detta mönster används som standard i UINavigationController vid pop-gesten och i UIScrollView med pagingEnabled. För anpassade gester, implementera UIViewControllerInteractiveTransitioning.
Transition Framework (android.transition) — är ett deklarativt animeringssystem som automatiskt animerar förändringar mellan två scener (Scene). En scen är en uppsättning Vyer med ett specifikt tillstånd. Vid övergång från Scene A till Scene B analyserar Transition Framework skillnaden och animerar: positionsförändring (ChangeBounds), storleksförändring (ChangeClipBounds, ChangeTransform), uppträdande (Fade) och försvinnande (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: kombination ChangeBounds + Fade
val transition = TransitionSet().apply {
ordering = TransitionSet.ORDERING_TOGETHER
addTransition(ChangeBounds())
addTransition(Fade(Fade.IN))
duration = 400L
interpolator = FastOutSlowInInterpolator()
}
// Övergång mellan scener i 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 utan manuell konfigurering
TransitionManager.go(scene2, AutoTransition().apply {
duration = 350L
})
// TransitionManager.beginDelayedTransition — utan scener
TransitionManager.beginDelayedTransition(sceneRoot, ChangeBounds())
itemView.layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT
itemView.requestLayout() "> Layoutändringen animeras automatiskt
ChangeBounds — den mest använda övergången i Android, animerar förändring av position och storlek för en View. ChangeTransform animerar rotation och scale. ChangeImageTransform — för animering av ImageView (centerCrop → fitCenter). För komplexa övergångar med ändring av hierarkistrukturen, använd TransitionSet med ordering = ORDERING_SEQUENTIAL (animeringar utförs sekventiellt, inte parallellt). Enligt dokumentationen för Android Developers (2026) stöder Transition Framework alla standard-Vyer, men stöder inte ytanimering (SurfaceView, TextureView, VideoView).
Vanliga frågor
Animation — animering av egenskaper hos ett objekt (alpha, translation, scale). Transition — animering av förändring av en uppsättning objekt eller tillstånd (fragment → fragment, scen → scen). Transition hanterar flera förändringar samtidigt: uppträdande, försvinnande, förflyttning, storleksförändring — och animerar automatiskt skillnaden mellan två tillstånd. Animation kräver manuell hantering av varje egenskap.
Använd FragmentTransaction.setCustomAnimations med Transition Framework: fragment1.exitTransition = Fade(Fade.OUT), fragment2.enterTransition = Slide(Gravity.END). För sekvens: setReorderingAllowed(true) — fragmenten kommer att omordnas för en smidig parallell övergång. För enkla fall räcker slide_in_right / slide_out_left från R.anim. För bakåtnavigering, ange popEnter och popExit.
Transition Framework animerar endast egenskaper som inte orsakar omberäkning av layouten. För höjdanimering, använd ChangeBounds — det animerar automatiskt förändring av View-gränser mellan två layouttillstånd. Anropa TransitionManager.beginDelayedTransition(viewGroup, ChangeBounds()) innan du ändrar LayoutParams. Om höjden ändras via WRAP_CONTENT, se till att layout_height före och efter är olika — ChangeBounds fungerar inte om båda tillstånden är match_parent.
Använd .transition() modifieraren med AnyTransition: .transition(.move(edge: .trailing).combined(with: .opacity)). För anpassade övergångar, implementera AnyTransition.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)). För animering inom NavigationStack, använd .navigationTransition(.slide) i iOS 18+. SwiftUI stöder inte UIViewControllerAnimatedTransitioning — endast deklarativa övergångar via AnyTransition.
Använd Profile GPU Rendering (Android) eller Core Animation Instrument (iOS). För Android, lägg till Transition-profilering via adb shell setprop debug.transition.profiling 1 — i loggarna visas varaktigheten för varje övergångsfas. På iOS, aktivera Slow Animations i simulatorn. Målvärden: varaktighet < 400 ms, FPS >= 55, frame drops — inte mer än 2 per övergång. För komplexa scener med 15+ samtidigt animerade Vyer, använd ChangeBounds med duration 300 ms.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också