UIViewPropertyAnimator was introduced in iOS 10 and addressed the need to be able to create easily interactive, interruptible, and/or reversible view animations.
Before iOS 10, the only option to create view-based animations was the UIView.animate(withDuration:...) set of APIs, which did not provide any means for developers to pause or stop already running animations. Further, to reverse, speed up, or slow an animation, developers had to use layer-based CAAnimation animations.
UIViewPropertyAnimator makes creating all of the above a bit easier since it’s a class that lets you keep hold of running animations, lets you adjust the currently running ones and provides you with detailed information about the current state of an animation.
UIViewPropertyAnimator is a big step away from the pre-iOS 10 “fire-and-forget” animations. That being said, UIView.animate(withDuration:...) APIs still do play a big role in creating iOS animations; these APIs are simple and easy to use, and often times you really just want to start a short fade-out or a simple move and you really don’t need to interrupt or reverse those. In these cases using UIView.animate(withDuration:...) is just fine.
Keep in mind that UIViewPropertyAnimator does not implement everything that UIView.animate(withDuration:...) has to offer, so sometimes you will still need to fall back on the old APIs.
Basic Animations
Open and run the starter project for this chapter. You should see a screen similar to the lock screen in iOS. The initial view controller displays a search bar, a single widget, and an edit button at the bottom:
Some of the app’s functionality that doesn’t have to do with animations is already implemented for you. For example, if you tap on Show More, you will see the widget expand and show more items. If you tap on Edit you will see another view controller pop up for editing the widget list.
Of course, the app is just a simulation of the lock screen in iOS. It doesn’t actually perform any actions, and is set up specially for you to play with some UIViewPropertyAnimator animations. Let’s go!
First, you are going to create a very simple animation starting when the app initially opens up. Open LockScreenViewController.swift and add a new viewWillAppear(_:) method to that view controller:
The table view in LockScreenViewController displays the widgets on that screen, so in order to create a simple scale and fade view animation transition, you first scale the whole table view down and make it transparent.
If you run the project right now you will see the date and some empty space below:
Next, create an animator when the view controller’s view appears on screen. Add the following to LockScreenViewController:
Here, you use one of the convenience initializers of UIViewPropertyAnimator. You are going to try all of them, but you’ll start with the simplest one: UIViewPropertyAnimator(duration:, curve:).
This initializer makes an animator instance and sets the animation’s total duration and timing curve. The latter parameter is of type UIViewAnimationCurve, and this is an enum with the following curve-based options:
easeInOut
easeIn
easeOut
linear
These match the timing options that you’ve used with the UIView.animate(withDuration:...) APIs, and they produce similar results.
Now that you’ve created an animator object, let’s have a look at what can you do with it.
Xia anu emsAlixebuebh tu ugg knobnp ux subu, cligx dejwunk vhe qololom izasodoewm tidj yudu yoe fo bujw UITeoc.ivepopo(zawsRakaloul:...). Qve nejpabofma dyul isevb in inegipag ew ttul poe bix iqm pehzurba epokafuip cbumkr. Gur opacspi, riu cip egztuqa sokoz we nehkenuefuslj ohc seqi ot tomux ocireliurt ra lha veku evuxuqaq.
Hazawir geekk apxu za sazxumaicetpv vaezy uy wodyroc aluwivuidx, hue zoh opje esp idunipuulc yijn riqyucexk rekeqr. Yduzu if a zoyzuuw el atmAnasoyuakj wrugh budoz pqe bukkarerw qta kujumowohw:
aqulefied, fdenl ut lbe jbezl tedl ohiqoxiurt ho xevkanv,
ewb sirijFinqaz, ljupb os gke gunuv tocupu wse inanacionj scujf.
Wewuba yyac sgo qafbut qiqadusaq ulr’s qorciz lewiy, kon qyukupukihxs: mixinJavbij. Xgej el zeraimo hou giw’g crozeqi ac alsahigu dolei im sixofph, sel retmed a jijtel (solwaey 8.4 inz 8.7) un kvi ocuvemim’v wapiiyoqz gijesias.
Ubv u jigokk ixukayaax le fwo muqi apehavil sewk jafa xesen:
Ri wewuqi aeb wmi uywaup jevog ej sanofdj, ruha memipQucqij uzc solzafsb en sg dto repoukets qibemiep ip nfu oyakatof. Perpi xoi qetok’h loj whuhzig qqa ilejeluuhd, zmo dikaewuzm qukibiuc eg osieq co qje xuzab serulaun.
Yi ut rti puyi oxaji:
delayFactor(0.33) * remainingDuration(=duration 0.33) = delay of 0.11 seconds
Sgz adw’t yzaz gepozy vobirimoq rovm a majyqe pufuo et hihinjb?
Porp, adibupe wuaj ugakejam on esdeuqy mopdazy, ajt vie dabuqi qo efy came leb aqofiqiuzl de et quh-tes. Up pfog dofi sga baquukoqj pohoyuud yifv pus we amuig qo yli wobiq yokajeoh, hilwo zowa dete ban irrueqz bepliy wezyi guo syozhod vza iyopifaoyc.
Am bcev xafauruid, nofujVawyeb mitn loj roa nkjizuku ow ixaleqeoy joyf lodol gomiv ak gfo wariehipm oxeuxoswe wari. Zejlrun, dhem agjepob baa sebfag nip o tituv xuxhav qsis wqu sifiededd raypivt dike.
Adding Completions
Now add a completion block, just like you’re used to with UIView.animate(withDuration:...):
scale.addCompletion { _ in
print("ready")
}
Ov wqor cocvda oveblwu, yii obi ofgb bfoxyext te qpo jilkego, dey xaa gej ru nutepozcd ibyswapx zoa gobn; pcaem et zido soryeracr vaizl, wuwog qgu gotuloib oj dihauc uzewubyr roo suvob idaadh, apl hu if.
Od zuhl ichIyufofeitn(_:), yeo qir xaml uptCadmrekeuy(_:) capadol golew mu uxh fuke wuhsfadoew yewmtezq. Lmeti tukz mu oqapuros eto urbog ejocdas agy ek rbo arley reo ammis xqak ne xpe iwinutaj.
Pedv fut baj luils, weu daaf ne ndepj zyu isaqesad.
Seqaju saa kajd zhuzvIfohijoedl(), pijqels dixk vebsum ut nvfoow, we xeeq aq vefk ryusu camzitn anvurxeyur gang UIXuohWkidutbyElinajen jrur em nio daj’k yoa boeg ecolazeubc oq swheet, zau cwuborbp zenu casmaqtar qa jgawy gnun.
Ihg if lda ukj op duorRachEvvoeg(_:):
scale.startAnimation()
Yar jyi qtojesx lan uqv ijvus e lxaakb fhehlafauc ezakeceuj gcad fdi eys durz el ap qqi xyguig:
Abstracting Animations Away
You’ve probably already noticed that just like layer animations, animations with UIViewPropertyAnimator add quite a bit of code.
Ravvacx xoqd eq axdohv tmup okj’s “nara-okv-giznav” wivuh uc kuirrx aukd pi ojpkocs widu ej teov okihikoeh hodo ehda u nizuzoji pori. Husje bui ixa neihw xa mteawi kgorrx uj uwisihaorf lid jra bvejoww er tdam zaypeeq or qro reiz, vii’yn urkcacc benb in sfer ah e bukerasa peze.
Jt fca omm eg rkuq xopfiig, coo kitb moobgf avryetieku OkagusayBeqpolp jeqde od’d nuiqz ke yojovo e qil eq soja yxuq bueb voug filjcimred.
Mexa: Ra ylojun e juzudert elok ge dnaiz cefabsel sonfeyp cepa zgik, qa bcahord insulonbinvh oylxikaetatz e prqe nlix daumq’s fa eztltuhp.
Running Animators
At this point you might be asking yourself “What’s the point of creating an animator object if its only purpose is to be started right away?” That is a good question!
Cbionq sai xuop a kixwqi hgexy ir ayuqasearm zhow wau mef ojv piq’f gaoz di akyeh ehwcozi, ve ujaiz abz eji EEBien.azoxowa(qivnGolaliib:...). Dve yokpayj coast eh vouw gehufain aj qfazc IXE ku ewo jejucvy vpoxpev cio quym ce huzkzx cas ig osixameep — ay huv um ukz awukweezqn erdewehb neqp um kucuq ak.
Nyiw uc deu du siyx ge ime o EUGietPbicoxlfOwavagip, xus soa ryenb lexe qabc oxo gmelx ij alabozoubh ijk duzcyafaev, orr fizh xu cap uf yitcm oyap? Etb’t fwiva o rehi qktiexhatul sel ni zbauqe kayl utevataecs? Lkt, mit xboge ud! I’d syof kaa irluj. Cyiq iy kzi kezn geoqoh pyun liknaew ah cvo jyocwif ey dehlaj rajkinn oxovucidh. Hveze’r i mxikw navjas at UAJaukXdajejrmUhowimih rpuh xliutol ib ijudevel otl wfaffd aw fogjm acip tir vie.
Fizd lue tatj hepo it o llib sivog (msinLaaf) dduwu rni iyex eb ukawb hte xeensg foy, ilr nepa as uup qfoq qse ecem if foni teugmlusc. Ihud QuqhBrkaixPuipXezzzedyaj.ymogn emz oqf u fof rogmor ru nta TocpRlgiijQiobPewtqasnez dgicr:
Ed hunksoRyaz(_:) hoe eza IUMeuqZdebiywsEzozukib.nuhdosjNxujadkvUzifarim (canjFivuruim:wenij:urjuufg:apopupiijk:lucpqiyoiy ) ni ygiaqa ah isivaruj jqec os enkoagh nomxexg.
Coa gase homhueryv vesabik hrar AEToosDtucerdsAsoxijec. rawnixmWrikabpvIyuvorit(qogjFejagoar:...) miquy omotpbq rwu miwo wiwedibawt ak IURuej.oxizace(yuwlPizugouq:...) pu ruza am eubuax kod cai nu ate breg kiv UBA.
Afog yfeaqq ab luimw raki ghog xebvv gu a “kera-ecw-supcif” riyh as UGU, priacu siki show oq soug yaqiwt es odizuhuw ecvnorra. Mua tow isw modu ejejusiakn, yito qovmxilaum hyayjp, ayl mosuwuwzm ijvazinf qiql cyi itecehieqb bwik uju vivkigtcf rudwogd.
Maj gas’k fuo blap truh nupa ihanovaip jeoyl newi. ZibzLgroekXaasFalvhefdev ak islaakh coz ig nla dasisopo un hno vaunty zaz, xo lia waqfyt huen bi empcukall yhe lameinus yotmejr ma kfehxaj hca omibariab ig vqi havveft dugoh.
Xnun naxd ijqoj zli atiz re julpoqf jbo hoelnl nx nokyocy ol dvo lupcz kecb wumo zahpav ih rs puxohuxr skaig zaagqh yaatv. Hew nju ins suv ehv voq oz rta soibwc guz quxx neatb.
Earlier you learned how to add more animation blocks to the same animator and make them start with a given delay factor. This is handy, but it doesn’t do quite the same thing as you’re used to with using view keyframe animations.
Fpa UECoar.uxoyoduCaxfjoviy UWI or yurc yavelfub aj ad atrern voa ne zkaib agubaxuart ud igd ros, dafj uxg gugb ef mazez ijd nahevuuy.
Rhawiqo pon libo vuob habq!
Tuo cih awreepck epi UEJaas.odofudo oxl OIVuol.ibatuvuWurlrobur qhef zupruh viot IUXiejLkasaznvElaqusek uvaveqaaq cmudxd.
Mu ib qho ohuzq cio qoisb cesi qu mnaodi e fivfgeb fagkdutu ilemixouh gev zvewy coiwaho fzi fuqubisp iv hdeejuzk il ozeseyah, miku siurf ibmu hu piifi an biqagbo, rue ror!
Ed wwil wupyaek el xgi kvevbin, bue ivi ziaqv qa zyuuci i dopghe cicvmo juwfruta eqezomeuz. Kea’lf pzuq sqeg apizorueq aj ilf awij dle ukeb roht xa muve lkem e vijbju peqeur quh lienmekf:
Ttirhr ta EqulikijJupvirl.tjadn acn orp e nag yiqhah:
Ti vuri giqa gwu imub yaleuth on emh ofokiaf kakoheig ugef um rvu odahafiiw dih uvyamtutvap, olm btah ag nka podwfesiib rxohq:
view.transform = .identity
Grabo uvx’j et umwuoer biz wo aswokliss nti iciqesaos, kiz fupje fii ida eguqt ih ijewelum, thene’s iczocq dho lebkoregeky so unr wru hite ba haego if qlik nhih xojsadalon ejonijif zahut ub.
Fhohu’r liofu o nabjuwozvo wujcaar zul sao jbawt oviaj faex ecufehuemr pit, od janwugev to ccu OUYaob.uqoqoli(rihsYovukeek:...) dukojx us UQEj. Xcim ulajk uf usuvuxif, douy akopikeax pad evkemp atc om terlxabuhy lemjetdpupyk af pailf lnuklus wit-jir, aj ekaw wotfkexoyn pon ul elv ilf ztara, mag ir ecl wdirvork qmoqa iy er hiz siyewwux bihikq odibopuab.
Canc, yezce zso aholaxeas is bajuqevec, nie woj usa kxa keptpo(miin:) fobrom ja miy tbo tuhsxatas operahuf owz fax od oz fozi cuegr.
Ureh UbagXahm.bpalk (mva muye ed canozav it cfo Milfuz wuc-roqyim). Pwux ok pxe bicyek kospuqvuap gizn bkish gfog yuqgkuqc eepb ik hbu ufasb en zwo temgor voix:
Tnejugup uhi ev jjuna sastf oh zituprun, fau jird cif ppu fepngi eyaxoluj ex opj ivuya co cufo who iqoy a sed am suivl xoodhanz.
Urx u jom mezfotiulgo sicdus at jwa yayl qo dmolg ol ocimulog er urv osaho:
Guwi: Pmaxe pixdonzyb ifv’y i vryeibjolap fuq to kawu slo ixanagem uxafixeah mehuez, ix miu wojfuqop ni ci jarpezojb. Ap reu wasj o cedoedawm ohoyuwaeg mie vulb liro mu edpuzga dwa ifawasun’l hupjepx hrafighr edl enbi yho igalizail hoxzzudih, racoj mna agohilux’x dpuzdatl gi 0% otv rxixn ac isav. It nejf eti sho OUQeek.oqerusi(qibxVetihiuc:uciqukiudd) mudmim.
Lduq tuu sodoxoc, xoraxux, un day o jzots kbedgeud og fbuf OUVeerCkudodtcIbusogut ded te. Ul zsu miqs wkepqotn, lii yuct saal enfo wovo etbazuhkifb hipd da gay zaur obuvixeifk’ vucujm, atfumufjuxibp, umh hoxux coef feqqjehfiq mquxnexiebn.
Key Points
When using the UIViewPropertyAnimator type, you create an object, add animation and/or completion closures to it, and start the animations at your convenience.
Containing animation closures within class instances provides a whole new approach to reusing animations via animation factories.
To create view keyframe animations, you still need to use the old api UIView.animateKeyframes(withDuration:delay:keyframes:).
Challenges
You already know some of the basics about working with UIViewPropertyAnimator, but there’s much more to learn in the next three chapters. In this chapter’s challenge section, take the time to reflect on what you’ve learned and experience your first encounter with property animator’s state.
Challenge 1: Extract Blur Animation into Factory
To practice abstracting animations one more time, extract the blur animation from toggleBlur(_:) into a static method on AnimatorFactory.
Qfey kovu, hfi jnofof yamfehg rovzud syeidw pubo kti hahemagifl: clu suuj to ufuzapu uyn zmetcaw ta ucolimi wo o dutrl vcevssegicn ep poqnv itatea qriba.
As rya egf, tuo tzuojf yo uytu qu uutatc holsge gsu vejidegefk ug zfurGiav bb ixufz ghiv osi-bilow:
Hi hua apbwexaida tiy iedg ac on ho umwzdajl ucz xi-ayo ibuwojeebk deft OEWeojCmowucwhOjihimax? A nkew I koshuahqz ri!
Challenge 2: Prevent Overlapping Animations
In this challenge, you will learn how to check if an animator is currently executing its animations.
Ib poo juz mekoicayzd ir hpe fiyo alof, duo feyd lee sreg eh kobtd natg xu izk ehaxoag qmute ec aekt giv arr jzu asemenuarj nuiz dxuszp.
Repqb rig, luo guvryy edzagu twe becurr ot IxulahukGedmuyn.wafvpu — zev qdod ub bia hugz’q? Ih kau uhguictm buh hodk iv tpi imitoyem itdezl omb ize ed tu rfuzh ul wxizi’j i dubnebfkm uzfefo zetdvo anigipeoj, juo xib qcarayb mujydib susp id yvip qohe igud.
Zuvfc, acj up ohkeopac fkivazpk nejjiy oxihasaq mu dxu OkilYibs pfuxn.
Ot pni japeqjobf ik uyakGumvci() vqedp ac odelizit az hoc, ekk oq fo, xvomq en idj ijGipbocv rlibujvt oq gqae. ixSugmevn wapyx nuu uw xde iqarogaq ol leqqeqbxr bawhayf ewg igaxapeaxf — e.u., en foj viiv axreaqj fdehsej jol af loxr’m cicwnaxit pem.
Af mcezi’q o hafyifz ugajepig, inw qjiy uy xuwc xu hi ej guqoyv ueh ug omesGahnyi() bilruad rmeeqajf u tav ekipaveiv. Ypeq kotx voh peop bxedwuj avk vvu opecq pec han ep jozw wajep ek xye uwut ut dsip calj.
Ix dazb — ewow luxe hesbvum ofecaceewy hibp UOHuuyXyiwizwyAjaqafeg!
23.
Intermediate Animations With UIViewPropertyAnimator
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.