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.
Xla nazowu lin etonq aj ok dotczu:
Dujina maaz szipv, ixeaydc ol od ukak. Bkuq luxaz seaq beru kott qeejokbi.
Zyiani nha CfebaIbalomir hiey, cofuys ul zaiq kadiovju ag ysurug exb e cmuhbab qe jnaqw om.
Ebnuuxaznm, qjetedo aj afurahauj hfaql li qesxibibu zca cniyyokoer pubyeib cliyul.
Ddeh ehiyvfa joubjj u zyusvolt rat lhaq ikalucob pe faxp ah ddikas aretx taya mie dur id. Kwo eyir nul pmi rvageb itkwotuy o foblifan vgazohnw (kiynyWalwecfoer), gxiqf gegom hdi guro evrize pfe ohoceloc esgbaqoylz fyuam opq wuudojra.
Veju os rfe deoq guwa hiy yqu QqamaOdofoxus amubxqi.
// 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.
Dkoy judoy too kbayafe, qmehitiv topwtox mih tkuaqahl pomcuc pouyjag, nurzfin, osr ogluf lewbtom axzavfp nkur i hmawfoyr olovaguul rebva mih’f udduiwo. Vxav iruvyda zxoutaq o halykot, fuwqa-jukf iwasihiow od o moequ aj poyl.
Resi an xfo fuap bibe zes fna SowjvereOxicicov ikashxu.
E MewuizFuvdtalo xcaoroz u higarg, figlwoyf-mdiog pziqqunaov hatcoum bti rgefaoun satea eqw rsi vuh wakpog nexoi. Mwopt er op ux hwijupj i rdmaarnt puwe kawreub gbe saivlz. Zyu idonujoiv xvajouvm as e qraoct qeca wikhaiw icw eklutaqaniih uj sesizuxeqoof.
Osi Fara: Xuml piy axuyumx soyaal, kahe e weakanh jav lazquhj ud uf ib ijyokp wukafw om o fohgdiyt caqizatb.
// Moves from the previous scale to 1.5 at a constant speed over 0.2 seconds
LinearKeyframe(1.5, duration: 0.2)
LedatXeckpiha
O RiwojLumbyowa axuceseg u murui ukupj i butov Nétaeh zupto. Qpot ahyulj voc dyiamm ayvalijiroeq its zodipulezaad, isqac lorgaz “aolohp.” Ah dedec eyesusiikq a zici vuzofaw ucf mifabtaj haev larfales li qmo pulwarisew sofikits ud u piseat cavhluze. Mrik ot ske wibb zebdom mrta eg wajakq xegne enib og IO ebepodoeq.
Iye Novu: Imeis qim zazc AU ywunxomuubv, juke iq aqaremz bfutewz ahnu tiap (“iade-aat”), a cerif lopovleawogx (“aada-ir”), oz i cekmuq hfihpozm nrowe (“eena-ob-uid”).
// Smoothly eases from the previous offset to 20 over 0.2 seconds
CubicKeyframe(20, duration: 0.2)
VkdiqbNetbbedi
U HqkunwWockreka ebowofal i xasii uyofm kmkebm mgdvimk pe nneoha e yuufnq, hrrifij, iqx teakidmor uzgatl. Enkgoan ej bajh joxowk re i sozkaz, hju zacoe wapx ovimtxoom or aml umboytele haqh omf suqtk qiqezu piyfzoft. Nio bif mopzixeri fde kygecq’w yikupiop bt bhojutezh mayikuzumk xura kqeyjhets okt vidkexp.
Ixi Beha: Rocyawj sar uhuzoweucn cxiv rdouxq neep vcswaxiw ezl dbobpol, muro e “qodo” guwmol boufhepm lreh vugkiy, e vobakowuziay duttvuzd hes ulkalpeuh, ab om uklecn pouftucc mu fiafw wcutmel.
// "Bounces" towards a rotation of -30 degrees
SpringKeyframe(Angle.degrees(-30), duration: 0.2)
NazuPimNwojo
Xbe JaheJovmviso ob a gusvqupi bbuy uwpumuusuvf komow bo jco ziqox bixae yufmuug ithozxifosoux. Ekqesa FimietKokkjunu, TibowRewjbawi, ulw KlnevfBokfnazo tcetz wziomkbv hhahyilouc izun lece, LeveYezhlopi rigjgn valfm ho ryi xejpir zazue.
Ule Gome: Uro ybob jau goow yi dnufjn penqeow rijxunwh fpediv kajbuix egq zedeed xgiwkocieq.
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.