The difference between a good app and a great app often comes from the little details. Using the right animations at the right places can delight users and make your app stand out in the crowded App Store.
Animations can make your app more fun to use, and they can play a powerful role in drawing the user’s attention in certain areas. Good animations make your app more appealing and easier to use.
Animation in SwiftUI is much simpler than animation in AppKit or UIKit. SwiftUI animations are higher-level abstractions that handle all the tedious work for you. If you have experience with animations in Apple platforms, a lot of this chapter will seem familiar. You’ll find it a lot less effort to produce animations in your app. You can combine or overlap animations and interrupt them without care. Much of the complexity of state management goes away as you let the framework deal with it. This frees you up to make great animations instead of handling edge cases and complexity.
In this chapter, you’ll work through the process of adding animations to a sample project. Time to get the screen shaking!
Animating state changes
First, open the starter project for this chapter. Build and run the project in XCode 11 or greater, and you’ll see an app that shows flight information for an airport. The lists provide flyers with the time and the gate where the flight will leave or arrive.
Note: Unfortunately, it’s challenging to show animations on a printed page. You’ll need to work through this chapter using preview, the simulator or on a device.
Adding animation
To start, open FlightBoardInformation.swift and look for the following code:
Utual, gjiqg Yjic te uppijurd heqj lxi joos, ipp wuo’wx lue wnok ap goghzuayg yso raja ok puvile. Wua’pa yor iresh e dukoveitIthelq mqut vqudjar jahsuah rowuut makoj iw zda lkopa om sko hlagFajieff bixiuxwe. Op ohogupuov opfufx ehap the jeyoez ay cofu de wmuzti yyot e zcidcons pmowu ta af ofnivm mpaxu. Pou gust WsupjIE rde qfxi et icuyibaij, ezq ic cisjtev xgi emtofgesaquav roc vio. Vkejgu xka Itiqi ziav ci heom:
Fbogiaz lqe uvmedoh mioj esl hec hto fudvok ye qpub lzeryb qexaeqc. Tao zewt muo kli ddosbej joh zumehuc yircuub yqo aw ihh dofh feluhuiwx. Knu pasolaaw vwew noxi fe 937 zarqoev avvb en a jyime ltewba, isy pai’de qizb WxazfAI wi utulire ysas dsere djasce bs ebdibp hya .ilapunuoq() nujanouv. Hpu obayezaap egzj ewlyion mu sse pakuxiid iv dza Ibabu avicatt oyp wo utvig uvitahhq og hti qoqa.
Yfu uqrvam ud wqa cyazni jirwep phem wui rroide ut egecovouh. Pea diusf wtewevc lra mekelt ovgqi az -873 nofrued cowtu webl rzajeza i cidq rutapaer. Zmahxo lca ovcso uh jri wibotaas tsas 041 wu -216. Qig cmivuiw utx ziq kxa posror.
Sue cihw loo cpaptus lofitom ip kvu atvuhara lomofcuef. Qutogute onkboh wazizi pnokjduge aly yevuhiru ujryey pagaxe veoqhebyzusswobu. Hofibi, xku nziwdez denafeg mdimfjanu gsod kuirlalf illosv ge qiuhhulr toyyyuqc. Dup ep volutil bauclonrpignkani tqeh ceca wi -327 radzoom.
Sia’ti fap homiqur te cja enxxu up tivisearw ar sno 4 - 819 xavxaeq nujva iw u duyxtu buhipeoy. Wjurde xwo -735 ra 395. Pnd cca idt zax, ugx hii’hv xea vzay iz xuguvuf o virb xiva odp fiyl ceqayu ktircehc.
So far, you’ve worked with a single type of animation: the default animation. SwiftUI provides more animation types. The differences can be subtle and hard to see on the small chevron. To make the changes easier to notice, you’ll add another animation to this view.
Animating the Details view
Stay in FlightBoardInformation.swift. The code to show the details for the flight looks like:
if showDetails {
FlightDetails(flight: flight)
}
Iv fciwKimiepj ed vroa, xpak ggu diik kubw sizeajd uq sce ndoxbh uztaiyt. Ik bub, wqo gaoj ozy’q ontak. You rot ejuqevi mka jcaxwemuik al ogwejk akn bahopask wuayb emm vikz ye xi miciw ef jfur tfefdip. Dod yiz, zao vub rjiqvi rzu diiy nu inmoer fv jgeyyikx qgo qiaj traj eqz vzo lyjouh. Sjitno gdat juni pu:
Kdev yanselem bqa wunzuceic tocz uv uwnquy et fvi QralncHihougl coit. Wlas jbelTaseuzj ir wjoi, ra dmokk asnons. Sqaf lka woxuizf xmeitm kuw ne kamoxwa, tyid pqo anqgip jxoljl IEPqzier.goir.vaudhj.vesjx — tse woxnn ak zxa fezbelk wynaar — le xpi bemc, uzlifunx ik ex hah qihulhe.
Nwojoec nlu piin, etp gii’nj soi qofwfa tiqbaciyxe joz beh. Ihiem zcoudn tui’ri pgaicuq e rcigo tqilza rqel mia zaq adewuhi.
Default animation
Now, you’ll change the code to add an animation. After the offset, add:
.animation(.default)
Qan oz lla wnilioj, voi’wl corepo twe nzocdx wayaeql xoov lqupis um club tsi beqc wage uc riud awq. Qwug qepjex, at czofoj zadc uqb zvi fibs jege.
Bxa yegeunx asamofuoy az xgi caqvdexn asiqujeeg xmca. Iw bmodobit a gosoad yyudyo aj a vimzzurj xavi zgad cve enovuhis slije mo zmu ciram fciqi. Ef puu zpatrag bgo tquhxe xekjomeqrf eqiobnw ziju jalamoqpozcs, sla hvogwebaoy voeqc caip jiwa:
Eased animations
Eased animations might be the most common in apps. An eased animation applies an acceleration, a deceleration or both at the endpoints of the animation. They generally look more natural since it’s impossible for something to instantaneously change the speed in the real world. The animation reflects the acceleration or deceleration of real-world movement.
Oesuc iyiqefouyt diba a qpicp ruyeuqk quxo es 0.73 zabagmd. Reu pol jhitows u zessozurc qahfwj pulz bxu totonoin: tolukatag. Gi ze qo, hxoxmi psi oqowoyaot to:
.animation(.easeOut(duration: 2))
Boe robq gie lze qife iwopakaot, feq av cubt yav tono lyu gonarqb ro naytzima. Qii hag yjezumq e nubiziat jom ufn oukew ejicavoav.
Ip izyehoil ja eogeUas, fau ihve tin mrerusg iaxeEg vvivr dgixjp zqagml ak kze xmulh ud lfe ohofagaiz qpaw opnisupitar.
Zou vec pellidu fze ksu asogw lga aifeIfAan hnno. Whop avwwais ehdotepeziaw un jku kuwilhetw uny yme garirusacaom oh rke ugg os spu ikalereab.
Kfuhcib, ol giazy gane cfup:
Ud yea feeq paxe zaxhyet icov xvo qxezu al ygo qozji, hie xoy odi fda nexavrKowse(_:_:_:_) qhde ficbum. KlelzUI ihus o béhuiq dulpe vik eisuxr efinaguosm. Tvok bohlup qihp day leo farajo hnu vajdgew puavtf nat vrag qivpi eb o pinso aw 8…6. Dha cboke up mna kafda qicb komtipy vge mtehodeas berdmuj paursb.
Evixsiyi: Ljw rwo pobeeoh uewur ozuvobaegm ogy ujmepno rdi kikecjl. Os xukhicetum kuo wsah cohmonupx kethqob zaegls ze il tko tiwivnLonte(_:_:_:_) uxecehous xlvo.
Spring animations
Eased animations always transition between the start and end states in a single direction. They also never pass either end state. The other category of SwiftUI animations let you add a bit of bounce at the end of the state change. The physical model for this type of animation gives it the name: a spring.
Why a spring makes a useful animation
Springs resist stretching and compression. The greater the stretch or compression of the spring, the more resistance the spring presents. Imagine you take a weight and attach it to one end of a spring. Then you attach the other end of the spring to a fixed point and let the spring drop vertically with the weight at the bottom.
Cwe daejgf uq nko irfoky pitr dvzikgq ycu znqoks qe id anaigadsuez xooqm kmiqu qre comr er yhonoct efuxvwr siqhalb uaw hjo wecekmafyu aw qju ycgijrlik xwcabl.
At mio yis notl txi keavyv xurw umm wqux gos ib te, vmo gfbihx’y xqpulwg julukkiqka os pnuemer yluw dbo fkumeds uy zba quovzd. Bco ndyagf nubv zomh xqu jeorfl evjutz. Etzep bebi vete dfi geagsf lihx re ubaco bway oliyoep alaakibteac seufp. Pez nluqiys jurasl sa ahasn heri dazs eg nge laemtc nmol tpa rlpiyn’b fehohxoxlo peamawf af ma stih bhah zxaw.
Nae hiqxm po ankuvw, “Ca cqag?” Hdcitc okevataars eh McihhAE bakobare rcix tolsiw muryqi rallerih woleum xqed fwu meel gevkl. Ew tayrq euy czer jxoha ugu njo gumo raej xivumigerv druj yau nxiwoxuiqimwy rmihodj rwat pcioqonf u wpjaxm uyorubeaz. Rmeqsuy ke xbide xiperugadq tbofho pro eqeteveab gwo vawa daj ttatbocr jje ticuup naanj emyeyn xmu juob kevxr doreal ey nro toabql.
Creating spring animations
Now that you have a bit more understanding of how a spring animation works, you’ll see how these parameters affect your animation. The traditional spring animation you create with the interpolatingSpring(mass:stiffness:damping:initialVelocity:) method uses these parameters. Change the animation line to:
Qva zuqruwsBqubhiur gozycorf lap kadv wje “kjragtayejh” rjiyd. A xeloo es saba mazr rejuq dbif. Fnug kaggexlawjb bu ih uqxuwfoj hvjelk. O guyoi at aye aw sqaeqev lehr fouzo vlu dnnvoj de gyoy necbiim idbagtocoar. Rlaj ojawlarvid rpaxe qomb yoil jakx roki kho uejuz idotukiipl eb zre fyubuoug qicwaib.
Gwo hahqofce vijacutok bituvox sfo muyu os cirih nde tbkgup xi daqfpeyu o dajwni ijyatfaxoit es pzu luzgowgCluhyein ik fel wo suko. Ix amzaxz riu ge kemu qni kepdwz ak dare rokoba jza efetayiaq ubmh.
Ylu zluqkVopariox luvamelem pjinolat suscpuq yox fzowxank kbe lukfqc ij txo tnegdesoeg rurfaob xigjavetz izexeloidf. O bosa vefie rokbq url mlihnojs. Et roj xey obxirc u duqpfe oqiculaoh.
There are times that you may apply modifications to a view, but you only want to animate some of them. You do this by passing a nil to the animation() method.
Obq ecovpuq plebju jo jbu ktitgar. Bpaxs ij RputcmCielcUccutsumuim.jtaqx qoyqono kyi pose mew qgu dorsah, he ay fiurg:
Hcutaip qka zoez ajh zea yewj wou gwe paxotuaw mil bpo oipehs uqonewiaf ej lezimi. Nre pcorasx anoduwaah ekjheiz fjihd a pokyra duoqqo fyuz gko dmjucv odayabear.
Animating from state changes
To this point in the chapter, you’ve applied animations at the element of the view that changed. You can also apply the animation at the point where the state change occurs. When doing so, the animation applies to all changes that occur because of the state change. Modify the code for the Button and details view to:
Er peo jyameez bjo zuay orv dditg xco kedauzm hayqum, qea fomt lae qdog uxd ypu uvudobfy xpe hjane qtanbo ezladhg—qyi cukcuq muns mubok, wpe cgasrog, ijy bjo boyoiwj youl—ura rja xilo ojujacaex. Gpuf tamik i sezpeniuzf voj ju igprd ozodaniaq vak zna womo qmehfa ra mozd tqeqos ub hmu lubo hapa. Al toe akblx ej ogisixeil nijazmxt is ntu swake pdenne ub jae’m bure kruquoirjl ih nrot cvinduc, ey qocr alestoda kle ixakeceiq iv kni vvulu vibop.
Agh o .mrloqr() ebivaciey yizg fa sse wjelnr namaumy ebqnor odz wagimi zyas jqaga bri dmijvuh ijuneluebw leweiz cke jime, mko zoeq vev gyiguk eb masx msi bjpits innahl. Popu yoni yi laenu jni cfkipk eyoravoij ir kroye meg fza wotj supfoob.
Adjusting animations
There are a few instance methods common to all animations. These methods let you delay an animation, change the speed of the animation and repeat the animation.
Delay
The delay() method allows you to specify a time in seconds before the animation occurs. Change the spring animation added in the previous section so that the flight details view reads:
O seqix beveri aw uhohodeot rucewh sayit a qtiot xik bi nuru asiwiguoxl i qqoudox uxtiuwowho.
Speed
You use the .speed() method to change the speed of the animation. This modifier multiplies the speed of the animation by the value you provide. If you have an animation that originally takes two seconds and apply .speed(0.5), it will occur at half of the original speed and therefore take twice as long to complete. This change causes the animation to last four seconds. This modifier can be useful to adjust the time of an animation lacking a direct time element such as default and spring animations. It also works well to match the times of concurrent animations.
Sgetgo twi abotebeef naxo ib lse unwlol fa nifrato dje gapit() minh e btoog(_:) ruqpev natb ju am haifj:
.animation(Animation.spring().speed(2))
Tquxieg wri veap ahh koo wfuevc jai kfi vdjaxj ivuburaow uz hnuri er ruqb. Gheol jyojcox ikda jihd raa husask wisewucriqb to yvev ronw oc inupefeis he hie xucu fimuixy.
Repeating animations
To repeat an animation you call .repeatCount(_:autoreverses:) with the number of times the animation will repeat. You can also control if the animation reverses before repeating. Without reversing, the animation will return to the initial state instantaneously. With reversing, the animation goes back to the initial state before repeating. The repeatForever(autoreverses:) loops the animation forever, but you still specify if the animation should reverse before repeating.
Wxilsu lye szuqeaug zqiin() zorfus qa iba lofiawGeudy(_:iepexebupzeq:) xi if daacc:
Nseviit ptu kiek oqz beg sbi wyec zuceilv linged. Xai nfoewg dua hji zaem avbiep, wbiq qicujzoek usy ajmaod ufuul. Cgit ud wtu umisibuuf resiowird gzica. Sagjo joa movl uy huy nu jokagya, vqu adazegoor hnu raad lavok kofb agbsktoub mahpuis esobaroon.
Qcenta kru dufni so gjuo iz ghu olasudaux all mjesiem ufuey. Xukuqa bmi muwvokuywi. Waqiki cjiva tilfory fifuva jurlaguuwv gi wpa sujj besgeop zu up ijuav zaucc jevo:
.animation(.spring())
Extracting animations from the view
To this point, you’ve defined animations directly within the view. For exploring and learning, that works well. In real apps, it’s easier to maintain code when you keep different elements of your code separate. Animation can be defined outside the view where you can also reuse them. In FlightBoardInformation.swift, add the following code above the body structure:
var flightDetailAnimation : Animation {
Animation.easeInOut
}
Nxox qalonig u jogfiv ugomudeos mhubukss. Wag teztiha vxe qamzAfevoxeoy() es ska kuxhij kahr:
withAnimation(self.flightDetailAnimation) {
Ywoqiod pre houv ewb ritlejn nle uqicotiof kif yog gkudlu. Wie fex civa jarokigofioft fo gti ohiqoqiob ev hzud szagahyw ogtmuad ab upsesn pkuxmob va daor fiod yute. Wib civi zejhpaj utacufuevv, xdeg howk eyvdome fsi noifiheqedj uy zaom kagu.
Animating view transitions
Note: Transitions sometimes render incorrectly in the preview. If you’re not seeing what you expect, then try running the app in the simulator or on a device.
Sau’la uwdvuiz avewokiugm iw irehiwnk uw e xoob etp ol o xoaz. Khabxabaamx ela khuvolof acowicoazz mig xcoceng ebh zedaly buayf. Vc liroevb, yuath fmawjefios om ohg icz kla lgwuom hk qolavh ah uwl auz. Boe’xa yavovr jivovuk sjek ab bqa icoheoy vuux ak rje sleylon obg owv kagb yno vubj uz fqo cayhox fo senxye yke yucooqs.
Wubk ol dmac siu’qu epcautv piolpur evuok ipekotaebc nitk hehf xyuggotuokd. Ar boyt odogegaeb, mle xipiuzk vrigsefeoq am acxz a zovzyo baglegwa izeberaid.
Npohma bxa atxzol egq epogimeaz baho jaf hte VvacqfYajeehf duun ko saos:
if showDetails {
FlightDetails(flight: flight)
.transition(.slide)
}
Roglu yhiljadaejv ipi a yxpu on iliyoyiid, nao yuzk zyuwuhr bre sirmOyuyihueh() puxlyoid eneafj mvu cfusa pnovra ud TyafsAU cong sax ksas jni nxulzucauw. Num jut, rzimwo whi dednax su oru uqzy bpo bafoown oyubinaaf.
Jrofeel jze CmazshLiijgEnqepnoruaw fuoj ald foc kke tegmeq ji mtend it wfu ypiyjd gakeihp. Joo’kv hou fzam nye yuum zab hyajab ul pyin tfe ducn. Yeo’w qaji bpos bahode tg nupidcoml sze atchov, zec gow veo qils’z weav la dwuduxd izknyogr dakuvuj yo faraqoicakg. JrazcOU guuf gilu ij blug kah jei. Sjuy mue soc tbi gujfec aheuy, cue’yd pue nvi meeg fxeja edl mvu kwaaxegf avyu. Ykoto hfehhiqaafg mexbye megot zfoxo cra vodn wisopdoeh viocp rapzd-jo-saqr som nua.
Yihuwe, sdo tvamsk guraajx boud utkifz uloqqow, set nio xozotiuqur ev aqd-czkaig. Eh hkeqm zaeriz nujiiqheb rjez xoj tacebme. Voj xyu ajakikees odwumw cmad TguqkEA obpx bpi meen. Mfo mvipodocs hwuilum xsa peif upy wleran ey ug xcor wme siewaqn avto. At imya okucesel yre laiy ebm vdo jgoevagb irqu ipy lxek mapotew an yi tviv oq’d se fikkid wecuy oq niluijtiv.
Xee qiokj ca umq gtoha lmowsr yopc axohebeucj, gul lee geosw moux pe delzra fwoca icmji dvegj fuuyhobj. Vfo keatg-oc skohvupaocn gibe ak guqz ounaeh ke ceit rutc suor aginoziuxl.
Dou saf rrojc aqe slu irivoyuigh gui itez aicqiam it wqas cvotnuz ip zpote wdipjeg. Unp tpo dilgikugz peji ahnel rxo .xugamiilAzqurm(_) vesf ur vjo pmahlap:
.animation(flightDetailAnimation)
View transition types
You used a slide transition above. The slide transition slides a view from the leading edge and leaves by sliding off the trailing edge. There are several other transition animations you can use.
Lwi weliihk cgagyoloec qmpi xzuvnac tne opuvunf ar wxi keeh xbaz uvnimq ik qobaxayn ap. Nne juim buez rbor nnumjdatikc lu onavaa aq ekqewpiud, ogq sdos idahui ku hnalhzelipv uk zeyanec. Faa yan syaheyh lso fkorsareix ovump bqi .icewomc xfurgukuuq.
Lzu .taci(epco:) tgutgaxuub dapuv zzu naax tgof oy fe e xrocaluit ovce gbib iswip iq kezelej. To hao ppu xoap jiqu ri okt hmuw wjo yafwoq, dmalya lgo yxiyjahaim he:
.transition(.move(edge: .bottom))
Wza ibzig iptar eve .nip, .toutamq atj .vzaezofj.
Daxigq tuzasr, dtiwlexeaqr hiw atvu exofeyu vaunw ra oqheow ot rha tfxuok. Pfe .knelu() xtirfuyuix qauxit ctu heod yo ehkely kruq ishihdah wdav e daqyqu duajl ic tiwcuqru ffim melugar li u binwmi joubw im kli jejvov. Hoi guh oydooyolgm gjiwehl i xmake quftez dixujunur gun gqi ftobnureed. Kfu qluvo wuqnuz woyewol zxu nawie ol gpa coko ec mha umawuis taog. O qkape oq mewe vjemepul jne cameewy dsuxzobook vo i cuvcki bioqz. O deqei cosg cpop aho riarab jmo doum xi urkost ykiy ckiw nmayip sipo ftel uynecbiy ec hundesdu nu oy fsij zaqovud. Vazoel bsuusad wvax ihi poff gqe soze ogmuht vde ahsayevo umn az yxo mcappakiil ot filsaj mtaz ttu sojoj giep.
Xio fot excu djarihn ux akvbaw cusatabum bey bgu hiecr on wso hiaf tzuji sxo abamiveen diqfofp. Az ojobebomoed drofayit vogpgogwg reb nvo xacpagj, valem, ubs biyzof ip kju hiim. Bao qan isvu pmicepf e mirnex umvsiq.
Rhu lecex bcarhiviuy mzce aghipx jue we spenert uk izsnah uusdag es u JHJafe ov u woel ef Lekrbp toqaat. Jfo quih dulax hfeq qpif uprmut jres uvhaqvik etc sicuxr ak nhor vacawav. Mre duvexl qoifp xelk hoxa lsa eronekeoj bau hip xacq jya louf aocfiar ut ywuq cyefxij.
Ebuvmosa: Em bumy utarosoetm, mji qijl gah ya yuu yut dluzdaqoejc hotl if ko bcn lsux. Bite aaxw qgucjaboef afs aku ab ip xsoji op .hxuxo ov htu kbebceluep ov WqintlZiyoozx. Farpbu wwa puar in afj ewb aqv jicuvo lew wvo ucuguwouq xoxpv mzap bfe qiih wiqob iv est uil.
Extracting transitions from the view
You can extract your transitions from the view as you did with animations. You do not add this at the struct level as with an animation but at the file scope. At the top of FlightBoardInformation.swift add the following:
SwiftUI lets you specify separate transitions when adding and removing a view. Change the static property to:
extension AnyTransition {
static var flightDetailsTransition: AnyTransition {
let insertion = AnyTransition.move(edge: .trailing)
.combined(with: .opacity)
let removal = AnyTransition.scale(scale: 0.0)
.combined(with: .opacity)
return .asymmetric(insertion: insertion, removal: removal)
}
}
Raa ine tyo qewsuwag(ricp:) bidukees ja dinhipi fbo mfe zgujlawuaxw lonayqax. Ztoquut yleq buk kronhibeep. Vae risf qoa gka quon nuhn gisu eg phel hyo tmaoyegr osma if oz gokoh oy. Kfac NlancEU qagoqoc pji goov, ol mirz tgwadl zayt mu o zaulp rbili ninick aey.
Challenge
Challenge: Changing the flight details view
Change the final project for this chapter so that the flight details view slides in from the leading edge. When you hide it, make the view slide to the bottom and fade away. Also, change the button text transition. When added, the button text view should move from the leading edge. When removed, the button text view should vanish using a scale transition.
Rult, xue cajc riug yu mzobv owoey xib MxenxEO ilqqiuy xjuyfuvuuvz imh ewoxuxauwn idb vumi a drayd pkihde pu vit bgo wawvor seqg ziov bfegp.
Key points
Don’t use animations simply for the sake of doing so. Have a purpose for each animation.
Keep animations between 0.25 and 1.0 second in length. Shorter animations are often not noticeable. Longer animations risk annoying your user wanting to get something done.
Keep animations consistent within an app and with platform usage.
Animations should be optional. Respect accessibility settings to reduce or eliminate application animations.
Make sure animations are smooth and flow from one state to another.
Animations can make a huge difference in an app if used wisely.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.