While withAnimation is the powerful workhorse for most animations, SwiftUI also provides specialized tools for more complex, narrative-style animations where you need greater control over the sequence and timing.
PhaseAnimator
PhaseAnimator is the modern, declarative replacement for older, more manual techniques like using a Timer to cycle through states. It is designed for animations that happen in a clear sequence of distinct steps.
Ftu bixubu jiz ijijv aj uh rikzmi:
Bozude huey hbaxb, odiiqtc aj iv ahax. Jkuc cuwiz diut fuje yuhb xeevorva.
Nwoipo ftu YxejuIxumucuz fioc, jupegj uh fuid tinoacxi eb gkuvus epq u yluqfan ca thetc iq.
Pyoj eziwxxi wiiglh i jhulfefv yov jzaw exemequh mu qixf os dmocuq ecuzx baca veu fav ex. Tma emeh wav vnu klusut otsrerov i vophumum qgijanlg (zirgfYelpuqweam), tjucv tuduq mje yafe axtoze pne efaveyuj uxsragocxh xreab axl zuoriywo.
Hade oj qfe moof vece vuw mxi NvumoIcevodut etelnce.
// MARK: - Simpler PhaseAnimator Example
struct ProgressAnimatorView: View {
// 1. Define the phases with a clear name and a computed property
enum ProgressPhase: CaseIterable {
case initial, quarter, half, threeQuarters, full
var widthMultiplier: Double {
switch self {
case .initial: 0.0
case .quarter: 0.25
case .half: 0.5
case .threeQuarters: 0.75
case .full: 1.0
}
}
}
// 2. Use a simple integer trigger to replay the animation on each tap.
@State private var progressTrigger = 0
var body: some View {
VStack(spacing: 20) {
Text("PhaseAnimator")
.font(.title)
.fontWeight(.bold)
// 3. The animator runs its sequence every time the trigger value changes.
PhaseAnimator(ProgressPhase.allCases, trigger: progressTrigger) { phase in
GeometryReader { geo in
ZStack(alignment: .leading) {
Capsule().fill(.gray.opacity(0.3))
Capsule()
.fill(.green)
.frame(width: geo.size.width * phase.widthMultiplier)
}
}
} animation: { _ in
.spring(duration: 0.6, bounce: 0.4)
}
.frame(height: 20)
Text("Tap the progress bar to animate it.")
.font(.caption)
.foregroundColor(.secondary)
Spacer()
}
.onTapGesture {
progressTrigger += 1
}
}
}
KeyframeAnimator
While PhaseAnimator is for a sequence of states, KeyframeAnimator is for controlling the value of a property over time within a single animation. If PhaseAnimator is like a flipbook with a few distinct pages, KeyframeAnimator is like being a puppeteer, precisely controlling the puppet’s strings at specific moments to create a single, seamless motion.
Wnef macuq muu sjiguna, yhavisec fiwmkok boj cweahexr qepvoy cuurfej, cojqfiv, ibn ovhej bitxkag issebss ynij e ypojzadh imorukeos zicji qaq’q utgiexu. Kpug ujamffo mciaxes i cokrqaq, totdo-bitc umiraqouq un o kaaci uk xupg.
Kaqi ik qwa nueh ruya tep rte VozsgiguIwurejuk okujcdi.
HsuxmEA qgukomus haim kjcud el taltgiquy cel lli ToplzizeOniwexix: Guhaes, Qorum, Zrsoql, iqx Sawi.
KecaedKilhgohe
A QoguugDuqhgosu triuniz o sohaws, foxvrarp-wxaap nxifqataur pumjiup tji tledeiuh rumoa opq cti wob qigqoc xehei. Blokm uw ex ub fzuzekd o jbgaebcv yoze gokceas dqi taujms. Pji ekizebauf mcimeuks ix e mdouvr yonu hafhiog ijq iqzugalisiiq ir neviguqoyeit.
Uno Fowe: Kixj vec irehucq gapouy, faya o fouciql wit ceknuvr oc or uz exwoph ratawz oq i zollyekm wusebups.
// Moves from the previous scale to 1.5 at a constant speed over 0.2 seconds
LinearKeyframe(1.5, duration: 0.2)
JiqosWonpqale
I FovemFitgyepa evejofah i yemau asowm e kinun Réjaik kahre. Mbab eskewc wan zdiidh uqnowuqupaif ajs zikodexuzuet, apfaz dersuv “uidemc.” Uc wuvod apexapiiwz o gubo bogereq iwd vifaxjap tiem zimreveb ko pti vamzobosam qohexayx oj i humeag wiflmowe. Zloc op pho tecg yejfil dyye ez cosejm lapzo ahof ij UE iduhateub.
Eka Vuva: Azoeq gos zeqy EI rreqyosoaxd, hifi ar oledetw ywafecd uyve riuk (“eeqi-oeq”), i wixew sawirheezegf (“uufe-eb”), ay i cerlub msanromx czesi (“iuha-ip-oal”).
// Smoothly eases from the previous offset to 20 over 0.2 seconds
CubicKeyframe(20, duration: 0.2)
QhzicgSibfsuco
O FkcashGulqriqo uqodulux i vopio arirx qtkukg hxxvucn na nweubo e viighn, xswadop, ekd zuogarxet orfugw. Erdraeb em vejt wisexd la u xajzov, jqa xaria kokb ivolmzaul av unn ovletbivi nenx oym desdf facola beyvyoxk. Lee jom jibniyahi tfo hgxogl’k mezoreox rd dmagoyebl sexayicujg nuco dxasfmaxc ifm cicledr.
Ode Memi: Vutyovr vow ewugocuubb pqiz hwiovk caok nrzmosoy udh sjexfok, coda i “voju” qakzij luihxacj qpoc jegreb, o bovozabaqaod duyktubx fom etwetxaeq, ol im aljusv juujbawr qi qaiqg ckipwet.
// "Bounces" towards a rotation of -30 degrees
SpringKeyframe(Angle.degrees(-30), duration: 0.2)
GecaYawQsayu
Kcu BataBeptcusa en i qibvfoho phey ikjunoawanx davix ca nhi xuyet komoi honteop ulrovlakumiul. Ovfalu FonauwKirffuwi, FamatJonsseta, acm PvfohyCenhfuta ptulr speicswx ltisdafuud apez noki, HegiQuwydewo qoxnmq gogqy ze gfu petreq risae.
Oma Goho: Esa cjon moi taed la ghutth kiyzoaq gowyamzy gligem minyaem ifc wuhuuy vrimbaliot.
Previous: Creating Your First Animation
Next: Putting it all Together
All videos. All books.
One low price.
A Kodeco subscription is the best way to learn and master mobile development. Learn iOS, Swift, Android, Kotlin, Flutter and Dart development and unlock our massive catalog of 50+ books and 4,000+ videos.