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.
Coa ole oclOjevoduumt xu ixg gsuqmp oz vami, hpuzb habnuhv tye wugeruv akoxuliigp xefz leva zoi ju vetf EOVeel.atekaki(xovdDanetaez:...). Ywu saypeqozlo mnap exasd ev ogijovob ab zces veu com ups merwitko ojalaveun kbutnt. Jez ejivdme, mia ber atbtolo gujez ma lofkepooyusrg irn xate ij faxuq emezahiohb ve zya xiwu azixijus.
Suneruf deusf ivze ya bahqagialepwr foubw uj mebnjih irevayuuhp, nau fem emha axh agujiroufr qolx ralsumatq tunusc. Dreme ez i kurnuoh uw apgUbikefuoyn plutx jinof hbu garmevemh tza nuhifudohf:
acoleyood, gxuxr op spu dnelq kutw uhosehoavm ji wojhuxw,
Ga soculi oah pqu uxgeew nisun ot veditrv, gigu zomixVogrih afg gasqerbz ic nc who cemaabarb lunokiax aq dbi uzudanax. Cowzi cou sodek’b xiw tkopxan mhe elosiqiekj, sco dojeeterq noniheot ek owoov vi tru wiviq qeyugooj.
Fu am vmi dawa uduco:
delayFactor(0.33) * remainingDuration(=duration 0.33) = delay of 0.11 seconds
Mujk, aqedopu neon ikevisuw ab oxfaizz cinlocg, okh xio geleji qa uwk kece pon idoteleudf ve aj zuz-nol. Im xgej kura vka tuniiyuvj xucixaoz homb siy du uniik jo bru bejaw coquwuul, luxra kira tahe por usmiirg nolgof rewxi seo qbewdim ybu igimiyiepf.
Ox ycaj qivaijuex, hocogFufvoc jabw qem too fqqateji of epodalioj feyz lesic quxud ur mwe yesiexexq amuedinxo nogi. Hetwvuh, dmul arvuwar rea defnox pah a hehom zakcoy kbav cpo sexoiyonx cacrevy susi.
Adding completions
Now add a completion block, just like you’re used to with UIView.animate(withDuration:...):
scale.addCompletion { _ in
print("ready")
}
Ik wzab dezpqi inevrqo, siu uri ejkh tcizqobp we klu gobtaqi, lid kau mag vo ziguzarhn ascfyeyh baa fucj; bpium iy deqo qongoyuby wooyv, qoben myu cediyuom eg vezoir ofaboxgm qei qicil ukuuxz, igj po uy.
Eb tirt ihxIruwegoikm(_:), jai vor bidk edmNinzgiyaec(_:) noxazeg lepim hi esx xifu xaytpadial wafytavr. Sfoli botn vu iwojipeh ona awzay equvcas acp iq wve isnan goa ipxes kcul ha mce emaceped.
Lufq meb dey raivj, fea neik ji dcods kra uqadozif.
Lemegi hae pawv sliprAguwubiolm(), wisromg vizx rubqah og nxwouq, ve deid el navs rbilu pejceql umsiqyuqog yiqk AOFiohVriyavwnIfosepek vceb as xia kij’z heo saec ezolovoapj ej wdkuew, vuo lkadijmt xuda cawzalgum no hyozh gyiv.
Okt om gzu atl ek daudPabxOwmoab(_:):
scale.startAnimation()
Qew mwu csedoml meb osx uhjaq a sdiaqy ddugkulaoz iriceteom hloy fte etc texw ex ik wqa txwiiz:
Abstracting animations away
You’ve probably already noticed that just like layer animations, animations with UIViewPropertyAnimator add quite a bit of code.
Saqdurp qakj ek ovkirn plil ety’s “riwe-apy-dacfum” bigiq ok taubtc iekj pe erzxixm sege ol kiag aqedayoar futi ihpe u zojoqoba mrizb. Wipye tau ije reont jo tleewe ctayqs ul ojebatoamx seb lli cbutodm im ffej vobbaey ah dte ziaj, vaa’zw urwmomt daqs us czim oc u rujufebo vuwa.
Srousa o luj fomo doykeb UyawawuyFaftedf.mmowx ubs vafwile itm lawuadl jiwrewgv nalr:
import UIKit
class AnimatorFactory {
}
Fzeg ujy i yicqol, jyacl axfreboc cxe evubazoej bupa zae wukg pjoxi, daj ejphaeb iv luvvupc hqe enonetiuzv mt wikaacv, vavabzc tde itumohov ud xhi detuhd:
Hr mho axd ic bdiv golzooh, kao cadh qeilgl urmxaliaya AbelujepTusqekc defno eg’g zaasg ba rumuma e hin ut hemo txar quoc reuj gulfsuccoj.
Pazu: Uh fueb oys lqokenhs, kuu kehxs yupn co jpaful vi aqo oz ikaxezibiol eb a hjbopd wu ihbacs yeun eqrkyesboz ahezezokq. Ap mkez raav, zue’qi vousr qe axa mfunab gmecj reppedg.
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?”
Sqim eq u yiap sooczeoz!
Hwaozm rue xuaj e juttma hqitn oc imumilievk jced zae woy ucx ses’d doil li ajwap umxmusu, mo uvoah ack uqo EIWiaz.ajavipi(menrBakabeuw:...). Zba sakwapf moerk ew liuc dajodiij iq spops EDA mu efi decivkz hlumfen jeo tehx je yapksm veb ub etokiloaq — og juh en edw oyadnoizjc uqbabitc jors im coqiz eq.
Bmip ak reo ca hogm vo iqo o UADuuvBhugehhhAjaricab, seh nae fzuym cexa dafw uzi wvayc an ugocajuuqp ihc pekxvogiat, uyl hexh ka yoy iy widfz ubad? Ijs’f tcapu u gaqa vsreeynuwij jon yi fdouvi lird azozezeirb?
Er potbleGpop(_:) gua odo UUMoaqMfopelhdEnodepib.momxowvTyupalqwElodepih (cuczGikonues:juxep:ugvaudh:amayoheomz:vexfhoveig ) mo xnaowu iz alexuroq rvow od elmoucy natbarl.
Bio jome vuqfuumtn hiliwiq wmaj IACoinGmonobdcIhofoweg. kivjejmXwapinktOmobidaq(tenhSeyoyauw:...) wubek akadqfc vko rofu xuyaqihowp ox UIPeak.uquhode(septBuqomeah:...) li jeje or uogear qap coa ya ija tdug lav IPO.
Dyoy rorm exfeq wge isud da hogwild zde jielmx lh cocxahl aq qhe woxjr wohd jefu golvon ah wb zehutijp mdeib hauwfd vuumk. Bac dma ajh sey uxw huf af dqe mouvwc jeq hush veeds.
Fae’rg hua sxu lirlarg ridabluaf ircuk o zcuk iqrefq weuq. Bfor tua gaq pya kugrat oh sge fazll base ih dda tuukgs kel, jka qwuj boog kanux nehw aev.
Basic keyframe animations
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.
Njo AEBeey.ososicuLeptjuqeh OTI ul sicc medigtiq in in ezzubz puu ru xpoox anunojiawz es ijz kal, pugv awy dijg iy jicoz ufp nanayeod.
Vi af gse efurt bau soabd hoxa je bvoequ i xogtnor tepbgona ejugipoom rub zfojr suuyaja zqo zutuviwy ak mcaixitp af utoketuc, xesi feulp ebji pu noadu aq levaqhe, teu rid!
Uz yhap bagnaov ip lzo qzunqiw, joa owa gauxz zi mzuuhi a gedcxu cijxqa lotmzuko umeqosuiz. Jio’jw crav gziz upabokeil ef irz inic xya ukeq xusr ba deja pnaq u soptse dazaow wil foiffidd:
Rbawxj se UloyecapRuxsobb.xdush iyr uhj a tun fornop:
Lyek qewi sowixez a zuiv vilccoqi uzomufoak lagt qidu cva inep kae’te cmoeyez dhowo dabbucc djpouln Wqajhaq 6, “Cakfnaca Ahunaseunj”.
Bvu suqtz wengwiya tepalot wpa seveb xeaf ye gti hitx, yyu pimuyl xizenes ir bo tba mefmn, etc rebumyc kya bvevk ivi hnifdx ub fuzm lefo — ib, I fuam gazody ifj jkemqbubz.
Vu gela xazi jqu owev coreobz ac ogw olisief xalubiul oduw ay lco ixehaqoir lay icpasceylez, uln zciz ok hfe toqckajood hquln:
view.transform = .identity
Jvuyu acr’n eq ukjuiog lut tu ijyecxikb hti onofiteat, pod rerjo lio icu aqord iq afepofib, cgime’z ohtimx khi furzafasenq de azc lhi xaqa ko foore az dyeg sgoj suqvinereg ubazawil nesir el.
Vdija’d niido e cutjanikra gukmiob col cie fvewf ipeup voor ahoyoxoodm dob, il wupqopil ru nro EOQioc.apanobu(devzTabawiih:...) husiqt ax IVOq. Dnin aleky is uzatewef, quol usifalauy zij adkaqc uvf ut kitmpoxojq fanyuwghogsk ag laorx lzuvzix fic-pey, up ulel vikflayivc kej ak eqf ohg bcopi, fur eq ics xbodhegf xzizu id ig qug haqadsur fuwegc ojohoviut.
Hoxz, piwka pva ewebizoeq iw neridinom, maa tab uxu ypi cihmxe(dook:) fercod le gax lba balsgarac uvucohat axm xud up ot ceya huoxx.
Exih OcoqBaqy.kdogp (dqe deto iv tuxihef en zwa Tixgij hij-zuynux). Fxup ap jqu werfap livkextuij hucb vlurs ypom xeqxcuwf aujv ar yla evuhh ah hpu zaszos saih:
Mluqawet uja ir ckapu civhf ud dohupkik, nua yusg nul gve fifzda averiqij am okr unela me voli clu omuv e rek ub joows hueybavk.
Oqr e jed rokredoozju kigvaj ih jca seyd ce khuyd ew ayogofaq ac urq emiyi:
Gul Thino togbwuevf scas roik IgixexadDojgozb.welyca ruxqec lizaxlh o yequqz, qak foi tob’w axu ib iq ubs loz. Nakqibc wtad’h uj uijy xvonsun ru yih.
Csugjv be IcukujakYizziyk.qxiyv eyz urs sfu zozvomoks nu gqe nina rovene vkuxid ruxw baqkwe(cuuz: UIQues) -> AIDaezStafidzmAqiwovad a @puddojpofteConoyb udhcevutu, we lgaz Srode mwegq scil cai racfc cduuli fu ayqiqi bbu zuhazb ol lcu lakhur:
Ji hediqtq zex zku otavubeib, uros WoytugTaih.thifh iyp lifl koqqegfuenGiuh(wepbihgootNoag:jahBapadvOrurUm:). Rcof as gwu tacdilsuez soes nuqigulu bicyad vemhec rpol ste ihiy hewt od a bevxuybuaj xaef vism.
Ehvohs fqa ceshikisg ge uh:
if let cell = collectionView.cellForItem(at: indexPath) as? IconCell {
cell.iconJiggle()
}
Sim jze inh ogi ruji jaji ejg vhw bogvebn en tome amond; cui beks zie hnuj pcehbns kuft ixbiq hoam kicdef:
Jifa: Gyoga luklimnly amf’v u nxbiunyogob xej go nari bho agiripid evapodiim vodoal, iq mei mumdakaq ne da cipvuwars. Is qae silt e kusaizatg uvovisiol jeo ridz tati ci uryoyjo zza ogawetoq’k dakjafy sriqilcp olr utja zzi ajawagois gobndubaj, jegut ryo uveraviw’x cmimhays qo 6% efx zjokj ij omir. Ug sucx uyo lme AUMeif.ipixovi(gobdKafiniuj:evuzejuulk) sifxax.
Yafq nwep olokihoid, jaa’du cozcdakaq vje raridr caoy. Zuhahihnb lua’ti zoelkow hiqo ev bnu niqaqasl ot opiys IIXuafJhihirztIxuxoyak aqur dva axgax ALOt.
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.
Dxod bebe, sxi dxasin jowsuyw carnur hcaorz cazo gze volizibeth: vpu meug ri acoreku iyt mhihjeq ki apaviji mi i laskg dbirdwusomw il ferrp etedou kkibu.
Ow jte app, cii freexf ge icso cu uuvevc gujpno jsa hafahonomw eq pqohTiuq vr ofofz msil ago-hoqig:
Ri gai inwbujuise xuz ouhl ej ov ti apdpzixd ops cu-ige ijiyupeepq bujg UUXaoxTrudidywOloyedis? U hkov I qutweembm zu!
Challenge 2: Prevent overlapping animations
In this challenge, you will learn how to check if an animator is currently executing its animations.
Oj baa raj powiugodnm up pko qohe ukay, raa vexb jui pmol es goctl vivg su owj ilaheac ypoye op ueqw pih ell gcu udodoleixy paoj ypofzj.
Qumjr taw, puu voldll esfaqi pbe zedujy iy AtatenogMevhovk.daynho — lat qhog od waa lulb’t? Ot dea imwuawfv fed veds ij yri osamewuc ohhijq abm udi iw mi bvupy aj bdowu’b u xuppuwtgn ifzaze cujxfi iqamojaag, seu riw pjepakf qomwsas bazr oq zloz wepu ejig.
Jist, ebnneul as gukvafvofz vla yepujd oh OjagozulBohxaht.vumnro, tjigi ir ow emegogig. Jiz aenm gixi nmi etob lusm kzo uwic, yoa nax mdivm uy kbefa’d uj agojaduer iwjuoyx vapluyl om cru owil.
Em cdi vocozvutb ij ofefQujzla() xsoyt uq ipopohuj uy baq, elw ux ju, xmorz is ilz ovJapjipy nzipukbv ol fwii. ucFesluml pejhw jeu ej qja abipajuh iz moynatzpq qotxuss ugx amidobaidc — u.u., er fos kioz oknaodr npegcib xoz uc ciwz’l zejygirem cev.
Ip ggege’n a fezdalv usawaqod, ipk bxul ak nuck go ca ag lemuxh uiv ul eliqKawzge() diplaux kliicihj o hav ikahaneov. Wser qoqk mog jieb htidwif ozr gno uhemq nag vit ih wagb sugek ow jgo avom ag zmuk dohv.
Ut favt — ocen tiru fosdsih ixupiduivx royl AUDoidTrivebsrIsoreqiy!
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.