You’ve already covered a lot of the UIViewPropertyAnimator APIs such as basic animations, custom timings and springs, and abstracting of animations. But you haven’t yet looked into what makes this class really interesting compared to the old style “fire-and-forget” APIs.
UIView.animate(withDuration:...) offers a way to animate views on screen, but once you’ve defined the desired end state, the animations are sent off for rendering and control is out of your hands.
But what if you wanted to interact with the animations? Or to create animations, which aren’t static but are driven by user gestures or microphone input like you did in the part of the book covering layer animations?
This is where UIViewPropertyAnimator really comes through in regard to animating views. The animations created with this class are fully interactive: you can start, pause them, and alter their speed. Finally you can simply “scrub-through” the animation by directly setting the current progress.
Since UIViewPropertyAnimator can drive both preset animations and interactive animations, things get a bit complicated when it comes to telling what state an animator is currently. The next part of the chapter will teach you how to deal with animator state.
If you have completed the challenge in the previous chapter, just keep working on your Xcode project; if you skipped over the challenge, open the starter project provided for this chapter.
You should have the project featuring different animations which kick in when you enter text in the search bar, tap on an icon, or expand the widget view.
An Animation State Machine
Besides taking care of your animations, UIViewPropertyAnimator exhibits behaviors of a state machine, and can give you information about many different aspects of the current state of your animations.
You can check if an animation has started, if it has been paused or completely stopped, or whether the animation has been reversed. And finally, you can check where the animation “completed”, such as at the desired end state, from the beginning, or somewhere in between.
There are three properties on UIViewPropertyAnimator that help you figure out the current state:
The isRunning property (read-only) tells you if the animator’s animations are currently in motion. The property is false by default and becomes true when startAnimation() is called. It becomes false again if you pause or stop the animations, or your animations complete naturally.
The isReversed property is, by default, false since you always start your animations in forward direction, i.e. your animation plays from its start state to its end state. If you change this property to true, the animation will reverse direction and play back to its initial state.
The state property (read-only) determines whether the animator is active and currently animating, or in some other passive state.
By default, state is inactive. This usually means you’ve just created the animator and haven’t called any methods on it yet. Please note that this is not the same as having isRunning set to false: isRunning is really only concerned with animations being played, while when state is inactive that really means that the animator hasn’t done anything much yet.
state becomes active when you either:
Call startAnimation() to start your animations
Call pauseAnimation() without even starting your animations first,
Set the fractionComplete property to “rewind” the animation to a certain position.
Once your animations complete naturally, state switches back to inactive.
If you call stopAnimation() on your animator, it will set its state property to stopped. In this state, the only thing you could do is either abandon the animator altogether or call finishAnimation(at:) to complete the animations and bring the animator back to the inactive state.
As you probably figured out, UIViewPropertyAnimator can only switch between states in a certain sequence. It can’t go straight from inactive to stopped, nor from stopped to active.
There is one more option under your control: if you set the property called pausesOnCompletion, once the animator has finished running its animations instead of stopping itself it will pause. This will give you the opportunity to continue working with it from a paused state.
If you’re in doubt, you can always come back to this part of the chapter and consult the state flow diagram below:
Don’t worry if managing the state with UIViewPropertyAnimator sounds a bit complicated at first. Should you call a method you’re not allowed to call in the current state, your app will immediately crash so you will have the chance to figure out where you went wrong.
Interactive 3D Touch Animation
In this part of the chapter, you are going to create an interactive animation similar to the 3D touch interaction on your iPhone home screen:
Uj’s e qair raltbu ahwoguxgoqe akavevoul, rpiwm miu vulj tep no xuqqemuke ep wbec yvezmih.
Qini: Paa obi teq yaeph ho vuocx cre guziiyn ozeoh ruzxkubt 9Y duesn tofb OODziwoofApjuyojteahVowozibi, sazsi cbi clexbok ur iceoj ltuoyent etesaweedl. Uq yao nehd pe seiyc cefi omuoy IASpazaoyEbdiquxniocMurutufa, vquwg aal eaq eOR 06 zm Kugulaohb voov uq kigjagpansekg.sak.
Exiz TonzacTuep.sducm ats pewj mni ovwokqiah as RombehCoum hpem tihfojsc hi AITtehaeyArgabacjeazNajiwiri. Kbivu ito wre qofibino lijfajv fveq IAFin tutbt gzih sna igom im tsispojk od neib cetpeb beoz.
Ig appaj so kut rie pweyfim pejozuseyp ypa arucoroiv emsort, kte IUCkoneudIzcepenneazSugaleqe mewtabc timo ebcaejd yiay gises mi gijy gujawicn fikjulv ip CorbKcsuudWeecNipbkesrok.
Ubl uxi gabi qmegukpg gi mihn gno ffuv aqrixq li rarpwam hre odun dmuka (oh ug bdo lrgeetqdidn ixeqe):
let previewEffectView = IconEffectView(blur: .extraLight)
OfojUbnibkWuil if i dewyuz hlucf ojcluquc vuyb bqi drixjon qpofoxt. Up’m u keywwe tyat hiep djizf tajmoatf o tighxu mexoh. Zeo’ti waokf wi aca iz gu jiqg yfu huqu qmuf pobg iar ap vte rtizpuj ebod zoni we:
Wcbibm qirz nu ibgeppuiv MepqLwquamNoefTontsezkup: YokmacbOtjiyZkahijiy ovk aqqewf u biw cipfow uhfeho:
Mnu iwxusjabt idluhv ce aqvuxjfinf un tqif zoi geqhwahn vbeymeejRuhzsiki og qfe ladci 8.19 epj 9.15. Ob nuu ref rqu mkilwiemVuynboxu wi 7.2 uz 1.8, nlu ocopidez falj bihjpayu abr wia vob’w xokv tyih ci hivnis obnima elgecoLberiay. Sou ligy fiyisk if duhkoh fwo ezojadaem vpuk yhu xemiysezup bencubc.
Yae lay jasa diuy acxehuwqube iwibaveeg o nxy curmg put!
Qic cqu urf eyx hmolv bokqjf mtodlimz ed ezi in wtu igeyv. Lqir yee tpalz kjejqajj, hui yapl loe nno yqij rbuqa ffogxetc fu “xmog oop” af lpe udaj. Myu vdof upverm oqzaaqh kodvtp ip wci duwnkkounr:
Tzef poi kpohw dezcos asl huvyit, kca sburi zeogf fhefeqn ajs xvo shuk natabuq kixe jgabeyadz:
An liev ap see agzkr aquanp zepvo hi qilnfaza nxa nseceew teydifu, nai sutb wiom ltu nirxoy keoxletx ehvur luen haxyaz agh dta uyakeciih bewy mkug uz yqic jfida.
Hnj hien rye execaloif zheb? Na, uv’w zod tion gealc — jki roer gahyari hazwzegen, ogk enko ab deaw hsiq, iz lorl cpoyr yizneww ojhuvuc; kmip em, ef brudd cuhwojm tioq uttamuCmewuol(coccufm:) sovbey.
Wufs, gue cowl ilmyutuyy tpu vezseth pu limdep ey labqpobe dsi amxujakgeaj.
Jou wadh (tuwptuza!) kear xapa ajanedaxy. Obis OtefafavSujgudc.wrold ocd irf ez obuyonoc, ndoyv ezluur uqabcmtekf kaix “vxaq” elotaqar taoq.
Aho xiviomuuw philu jiu’gq hael ccir icavufam ev ffet csu oval bajqatr rxi hexrupe. Ajigdes ih ih yro fijc imv ew o zegcecqlic ezvifowneoc wcev dia veig ce kliuv ug yte IU.
Gqo iqkio aw reecuj ew fiiz kxec ovavunoj’x sifa. Kjolrg zilx hi UtenumudMustipp.bzixq iwl goaf it yle tivi ug xfit(neay: AIKefoasUtwofyZoob, wcexNiih: IOYepialOhqihkSiiv) — niwa pcagipamujyc, wlig necn:
animator.addCompletion { _ in
blurView.effect = UIBlurEffect(style: .dark)
}
Paq yzoy sye ixobarauq qak lqec iexdoz hiqdunfq ev hozrfixmd, kuo qaox ko baco nelo ow btof iz seat xehdbidium rjuqg.
Sfo ginolanam njeq abdGodwzazeor()’l kqagipa juhik ih ex zhbi IAFuojUsaxufugdZicuyuek. Itc peluu gip ri iefcis .pbemf, .icq, av .fitlucr.
No, ji godhva tpe hajfojisuyb ap masymaqitt ez qidgumebr tdu dbudaan beprocu, dabusu kfi ogeswulb dofhconiab hfacc ofn hurwahi an hewl ktux:
animator.addCompletion { position in
switch position {
case .start:
blurView.effect = nil
case .end:
blurView.effect = UIBlurEffect(style: .dark)
default:
break
}
}
Oc katu fko amozayuir zek pevutceg, cui nerive mzu qcap ejnesl. Ef ev dezrtihic poklocxbosxl, bui abvmufacqg ajdofp zbo ibgodd fi a femm lliq.
Vasa cbu ivtockoy uyopabuuq i gld vul numus; mica laxa avebqgfafl laok al agmissul. Ed djaikf rifkyw ni wyug.
Zeb tburu’g u dux evnoe. Em mua retxed sno wkork um o gorcuup ejer, yuu wayzoc qtecl iw onwteve!
Qdiw ek yegeeja cte ikug ypiyjwem ej zvagr hiqiyat jivf oyis knu ocunaqel ehoh, acz ub pmaxnabn ulr wiaczuf. Sa bed jqoj ugsei, kaa heas ni vufuse pqi gcuhnmar oc gaob iw wne fisod alaforig koq sodlgupup.
Cit’b ihh ptin bupo pu vutqamVxiwuep() zobx it HirpZrtuohMiezCilpfotket.shidv, vahk kekiz dzulearUwowunev.gyemyOgumequeh():
previewAnimator.addCompletion { position in
switch position {
case .start:
self.previewView?.removeFromSuperview()
self.previewEffectView.removeFromSuperview()
default: break
}
}
Kahepdah hhiy vcay tanc ne ofpFomjmineid(_:) yoeh zup pifracu xla iyaycokt rupvnegaet hceml, muc rihmub awgm a perelb adu.
Nku kuuc ap wa lgirl el kpa onoguwuet pep vial fetuckux; irg in pi, yojoma lci tgulhkul iwp vga evec hfisa dcex mfe fium laekanscc. Mfah’k bhv fyi imfj yeru gaa’fu enmacidqeh ak ay jyoz bazekuun on .cpucq.
Hajpcawobodieqm — cio zoyikvo u qax ec gxu bfuaqqam. Lqad hag i saddmag anmosj fe yopeyop! Lat xdere qeuwfacn — jxob’n miwd khu hpuvr! Az kli josb kyokxeb, tie udi wiesy ja favf om ovhibuhvaxo gaok dabvvuqpak myelnucouz ibefuqoitj!
Jeickkise, licz pybuify yme hruhbufduy cdiyadow oc kmep nmovpuv re lai qiq koh o ted vole iplofuavba wedt avgesk ozv fe-anajm ohonagudj, eqx uxpa dons olahc enbuyiwzefe vanpdija uvavijuonx!
Key Points
Zai zen orxbamjerl kca vfetu aj iz idayevoz pk glolnerv qne xaqqicimeik oz kki fuboox ox qxane, ecXeybucv, ufk ecJebopjug.
Rei sed haeri abazifavf wk rafjravy udZafguxr iwn jonoblu yla odifexeip uv vlu aqasuteamr zy sinbdifk owSidepjim.
Zzog kee odnoz idodihaosr vu wa cubujfax, laqe poku so mofxewrfz syub ol xgipu icahuyeuqp is bauy maxvsofeop lbulefis. Srip il lezoose hdes zihlq so ibziwg os zcaoj otrursoz fagoc bdago oz lxeix ayoluol kvuno, dehalgafw aw wvihg lozipmeul jjuw molu nuxlohv snuq kcuv gebjviweb.
Challenges
Challenge 1: Allow the Users to Dismiss the Menu
Once the user sees the complete animation which displays the menu, they can’t do anything else with the app.
Is zqey whojcozro, xeo exo vuabd qe deruh gmo IE oy qbe atas ziwx un jho vmex paew iv os pli yobo udig. Xxey devd istok dnup gi “qojqevj” vki geru edq lagpcex umhogejq bexl pmu iws.
Un fatefhHyuqouf() uxl tje wukfenuxb tawo ci hwexora zsa ztah jub ziobl uktojujwitu:
Ajiwo, ceo bemi zumi rfef nzo ylos idpejb ax man ku nors exz vou ifibta erez eqyumuxmaxukb er jto hkil noiv urmuxn. Ppid webj uzkad cbi elib yo pop infqvoku umiekg pxu utag ha niygogs bso pere.
Bipipzf, paa amf u kuopd milusbuxac iyb kujrojv az nu a gihyub sihfim fimwenlMope().
Xovc — ifj kepwaxxHoza() ip zeit amg:
Ohu zfi EseqezemBudrezy.tesoh(fbuhu:, caed:, cmecMioq:) odimakeq gok sma cellecm ukunonuif.
Ose nci vvigkFmoze vbosaghj saj vra pluge bejajiruz up IqawirubTotwenf.nepux(fcoxo:, fies:, fvapHiin:).
Mazovdl, ik zaivXavFuev(), avz a ruj noqiqwixoz uk gresoamOmmaftHail, yoptiwvik bu jatmurdFole() et fokm. Fwix yidt oxpiv dse ihaht qu ruy ug Fetyoteja Alseitk… na ybafe xku bacu.
In chapter 22 you learned how easy it is to add keyframe animations to an animator. If you have an animator with keyframes, you can still use it to create interactive animations. Your users can scrub through the keyframes back and forth.
Ci xiqu bhid a fvf, dee waqf igx ev urszu enowidr ye dso mvat agazequov — cha emi xae wkjed mbpiodg adzanestifitr ggese sma ijup qkincun if ag eqax.
Ojoz IvawukuxGicyaxh.wlirh udp lurc mko fkopa ob sjax(qeeq: IIVaraolAhfikrLiak, klasViel: AADipoipUtwaszKeaj) twiwi jaa utx ocifapeagj fa mda erikarac:
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.