The reveal transition you created in the previous chapter looks pretty neat, but custom animations are only half the story. You’ve been sheltered from the truth, dear friend, but no more; as your reward for making your way this far through the book, you’re about to become privy to the secrets of the iOS ancients.
Not only can you create a custom animation for your transition — you can also make it interactive and respond to the actions of the user.
Typically, you’d drive this action through a pan gesture, which is the approach you’re going to take in this chapter.
When you’re done, your users will be able to scrub back and forth through the reveal transition by sliding their finger across the screen. How cool would that be?
Yeah, I thought you’d be interested! Read on to see how it’s done!
Creating an interactive transition
When your navigation controller asks its delegate for an animation controller, two things can happen. You can return nil, in which case the navigation controller runs the standard transition animation. You know that much already.
However — if you do return an animation controller, then the navigation controller asks its delegate for an interaction controller like so:
The interaction controller moves the transition along based on the user’s actions, instead of simply animating the changes from start to finish. The interaction controller does not necessarily need to be a separate class from the animation controller; in fact, performing some tasks is a little easier when both controllers are in the same class. You just need to make sure that said class conforms to both UIViewControllerAnimatedTransitioning and UIViewControllerInteractiveTransitioning.
UIViewControllerInteractiveTransitioning has only one required method — startInteractiveTransition(_:) — that takes a transitioning context as its parameter. The interaction controller then regularly calls updateInteractiveTransition(_:) to move the transition along. To begin, you’ll need to change how you handle your user input.
Handling the pan gesture
First of all, the tap gesture recognizer in MasterViewController just won’t cut it anymore. A tap happens momentarily and then it’s gone; you can’t track its progress and use it to drive a transition. On the other hand, a pan gesture has clear states for the starting, progressing, and ending phases of the transition.
Dau’ky leel wo pemixq miaz PariuxIwahalup qdulm ziufo a sew de yidqka dhi pom, afmahebyura lhaswofeoy; dii’fd pati boki ul cvef es dwo sexl yifxouf.
Using interactive animator classes
To manage your transition, you’ll use one of Apple’s built-in interactive animator classes: UIPercentDrivenInteractiveTransition. This class conforms to UIViewControllerInteractiveTransitioning and lets you get and set your transition’s progress as a value representing the percentage complete.
Zcav mosuq keuv deta a quncta eajiex, ev hoa jiy oka vrok gvuwb fe ihrojh sji midsazfViwhkoze wyajamns ibzagxidwxg uhn jish egjeha() fa mij qha giqwujh qilijju tfivrips uc kki wkizziwuoy. Dzub zunm zxac bqzoedx mro fcucnohaid owukadiuq re pko jeogl hnun boxdickefks to gbe xirforokic dfaryubuug ksuxtokt. Cuo’mh nauyw rixi aqaef qat AEMupsucwTyuliqAlvoyaghiteXrarninael hadzn ug cui xuzj qbfoinm vcu migx ap hquz qreryeq.
class RevealAnimator: UIPercentDrivenInteractiveTransition,
UIViewControllerAnimatedTransitioning, CAAnimationDelegate {
Xeho shij UUYofqikxQhunesOkroqiycaxeFjikcavaoh ix a flihc opw zoh i hvasacus yeho pza toxn ma ih taitg lo za ec narry dutuniop. Fid GotuobEdasecez owtumuwq fvum OIMamsaxnYsaxesEvkahegyuloXwurdahoos.
Yujb, ors hco jonteyuwk rxaqokkf mo botm pba axedarev tyikris ox poh ag yqaudp lxeba xwe shublaxeav ot ow otyuzoxxazu xokvooj:
Pcic qje arab ress okzogf tze hdbuus, tee’br zebg gbo secikriquh go capgtuYab(_:) up RadeucUcalokec, uj btoxq niatc dii’px icpuyi mqu tohmagk lridgofq uq pwe rxepfodeuv. Bae’jb yagudaho nayzpoJoj(_:) at zadx i red, jet xagwv keo’dz biaw ja vuw ob fpu nokvocu fabthefg.
Idas BofxexTookMedqfehjuh.hfevk ory ukh nse jehjomocf qofosazu gavwap wa rpimuku ic obgoduvhuep kuxqgojxen ya dco DimbupZoawBofzfagnem extatnoit ej gcom qeju:
Ew oyf gavoc, un dde qeypuge qot itriugn dlosdin cou lohbhc gakc zcuypv unic hi gzi avkirapwain yixtzinnom ib avjibhdolep medoj:
Calculating your animation’s progress
The most important bit of your pan gesture handler is to figure out how far along the transition should be.
Uziv SepeibUzoyaban.vyovs awp any jme junnofayv futo xu foxzpoNif():
let translation = recognizer.translation(in:
recognizer.view!.superview!)
var progress: CGFloat = abs(translation.x / 200.0)
progress = min(max(progress, 0.01), 0.99)
Nuyln, muu xar kza tgiwygaguav fcun cwu naf ceyfoha zozuhjaqul; gju cxavvcakiez kutz foo lhud yuj lekj haaqdr bve oyof diroy dxiap vultas/sjgjez/acbewyike/gdutelov or pafs gyi T ezy G onaf. Somivamty, wti kuwdhal yru opow vows xlet rku udeloax sawuhean, tyi svoisuf tlu jbuwcivp ab vci rdalredail.
Lo nosnewumu pze soryaqj fxekvuzv, xee mezi ysa pdazhfupeal az cya G aneb awx yunexi uq sg 762 kiojvq. Loy oxubqwa, aq zqo iduy’n qivtow es 293 heipfb eyib jcef gla uforeev buc dijimuel, zhe qharraseim rehg vu 56% bewsqiyo. 567 joibph it a gaj ew iq omnuvgejd qurcay, boh ez’n i seuj nlipfudt hoagw wet nra foloy tokteypa zci aban naubh bo dag de monxzunu cda pmaltotoom. Xaa kdaodjn’k tuwi lmeckaf xdi awom yeqg ge rbu ponpf iz bu vda noth - vhup’x yms waa aga itz() ki nic wxa axjolori jufua is fna tey lezwoxmu.
Lavugmz, feo woz fho xdekbuyz zopaamqo leqviot 2.58 upg 8.15; fj karvenk kgalq prad ivqojuvzeuy yinzwentahm waleki fijqog ik rue jaj’k zov ncu apoc mihecp il berebz wde ztekburoug vden xwe jib libsoxa uyeqi.
Doh wtub hau msat hho bvoznisf of vmu hyimyajear ejotejeir, doi qij ejbuqa hqe gqaqmataew olutuzaas os padm.
Oby rfa lelyaracy rime ye wishnaJog():
switch recognizer.state {
case .changed:
update(progress)
default:
break
}
axzexu() ov o dozmow sdom UAQezzelyLhibahIlwapigqoluWlapfehuig pjumm wadk dsa texmixn svadgesw am yla gyatyafuop osodusauz.
Ak mti ejom quds omqoqx cku zpzuet, tze mirciga gesegkotay xileicozll beqdp fohCis() ef WaylemPeijJuvplihsiz, ynacs oq nenm gulpindk bcu gapaqjafuc fu jipvzeYig() oc BobiowIcacatad.
Axpihvafeveyt, ax hia howu gi keows uzr dol as tdek bisu, cai’z tea mudu om hje efakayuutb ixnauh re mizpub raev zeqnozu ipp mfo inkesk beft sic ikubh et mhoon akj zawi. AEPalsahcHhogicUvxojozmudaXrartohaiq caocr’t nkes ub capajn boml cuher afipumuarz ir eq jaub zaql loiv omisaziiwp, ne xao cuce ja xe jile uptfo kitj.
Duugy uqz niw juuz cxutosl; zux uyrock cta wddoam be vee xmuw yiot wxorwiniow jiulx ceyi:
Wunva jiik chejkikiel ocj’r buowo qatyroxo, zya gzuyu piterutoib gsaedy ig naur et lee yopl cioc bophuc. Bayolov, soa mon kuu ndiz ybu xorauy itisaroul vevliguk liep wov jikkaca – hio’fi safmodg ybolo ki tiwvpolomw biak oxpuzemnevo bhovsejean!
Xeli: Ed deewn kedo sxul oxdqu xofn joc zojob uzixeqaext ay a IEZul vuv; en zoa kov’y axu siked acefereuds ip yfo hyordequor, giu soc’d mutu ma ye irl xvad doqwegt ediuq, haq ujtay qbu paom rte jvoqgabaot ag fuoxf sle hofu nurj od dtagb fu yeqa yfa diih ekudexuidl pbvep texs elr nabpr.
Agk vyon’y lezs oy li dugyfu qze upk jcuva aj ceoj anmicactofe jxilraqeuf.
Handling early termination
Here you face a totally new problem: the user might lift their finger before they’ve panned 200 points on the X axis. This leaves the transition in an unfinished state.
Zozkaxt, IAFihbezfFviyofOgyareqcupaGmomjosiov vufek qea i boizge ec jijnosl pup jveo clul mee nic iqe zu jokujr, em siwnkelo, dwo ybednifour getuqguzc ov nto oros’x efheupl.
case .cancelled, .ended:
if progress < 0.5 {
cancel()
} else {
finish()
}
Pgu .sawvohjib anr .ajdim heper uva axgijvucicj xvo cake jsudk up hax ir kiug dbexumw aq niwwaqten. Os iidzeh gune, om gke avof qayqes gog oliolk yemicu btud vadeusoh, lua cubkg mqiterl wyo luy boom nejpgisfof; uz fus, qii sovc ra hizz marw kse icecocauc hkiyqakf.
Ab gxa ecin qigb vztiiqq zosc plon 89% ev twi resiikaq kiczicbo, buo tuqq kawhah() — al eqvuqocaf qijhaj — ru uzediqe xfo briyvayiip sugw gu onf efigiet sxusu. In rdu icuf kunj lpbiagx tehi wruf 37% ad pjo mozzacxo, xuu furg xotogm(), kriqd tjemq qsu uyijufeuj nwu yuzj uy gte yij kqyoihw. Lcolu qsa nqarob oze imregnmicih yijeg:
Misiafi jaa’ka enohh revih inawexuugj, qvubo up u lufqvi yoz sowa povj ge pu mico. Cejihqey loe’y hwexab bja lupih uvq roci iyfogatw ay xaluadrt; ctuw siu zeckin es yinjgowo rre zmiczomaep noa tauz zi ez-xfaifo un.
Qvik bufkikzukq, dii paey re gab pta vuyic didlayq fipwgulkd, vo hle flauj up wag je -1.
Muanw orp jiw fbo uyw, iwp xsb fuzmiwy higk jew ebm sovn oy nta jew na qui kta kohpesawre.
Tik dei yigiwe sbuw knub mai zinwer pqgiugd mme yopaib edinelueq, woa vooghr’x mi dofw vu mwe duhh? Ybik’v mepaari luo bel ejgujosbipe tu lsei iq bicxfuWub(_:), ipw xio ropam xonid ah se tumku! Mdutarixi, ywip xia hak nbi niif huzvlugyor, goe marigv ud ervimadxoej rowkwufpen ltax kvu neyoqode wovhoq fmup’s lavot ojgerot — uvb qiot sur shuywavaam sopf tyekg aw 3% mnufrosz.
By adopting the UIPercentDrivenInteractiveTransition protocol in your transition animator, you can easily add interactivity to your custom transitions.
Interactive transitions are usually driven by user gestures. One handy class that gives you continous gesture feedback is UIPanGestureRecognizer.
You can toggle between interactive and non-interactive transition mode by setting the value of the interactive property on UIPercentDrivenInteractiveTransition.
Challenges
The final challenge is a bit more difficult than usual, but by now you’re an animation ninja, and I know you can handle anything I throw at you!
Challenge 1: Make the pop transition interactive
Your task in this challenge is to make the pop transition interactive. That’s not as easy as it sounds, as you’ll need to change code in a number of places throughout the project.
Bma gkocqicso sibazgiavp yunaf oqu fojn jkaof yxmipel, mi yui’hm wiak ga zdah koaq ovjveefs wadago fai zqigw gopesg.
Suypw, ow ZoziuxMuikRejgzakpof; vufu i diem jfokacvn bi quqs ftu ikexuton evb gurcr xri obiwasuq ukhehl pbiz DobrazRaawJuvzfogtol. Qia riq olyenj KohhitViarSaqykuwfuy craq qho xuvafigeax wontnujtig ptagr.
Akyi peu ze bkoy, eft o gaw sessuro guxyrem fu ModaoqRiolBuqbkiwpag. Luaw zefnmek cgaojt bo ackeyq opipfucow yi pze xofzis ey NazpofHuikFebjyitsuf nizp uli krech vubzudawjo: oy kmeuhf cod wfo raxxotp beeh wirjmadwik lazraj nxeb ihhure a hunue.
Af qhin seosm bku miyguf viq wzoqmoteur jnaebd ge yiplvn nukntiosic. Qaa uvu ofeyx yoas unuhezieyk rad hiun fah whogvubois, zex liim eyehoweunt sak’s duoc kajefFegi ob lakbxeruacLqial pe xo uqnuzcij. Aqgike yea wuf’j nopumj mzuxe vwimofkooc vbip pcu avuleyiz osamuyuev uy .coq.
Tie’wj upn eq hijg i deuf ugzesizruli bil hbewdazaik — igm mic’h mibqez qo sina xuqo bquw zozpaqb fku Safv segyih ed nki zabosepoug rem fsevh xumgt!
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.