In this chapter you’ll learn about stroke and path animations as you add a cool pull-to-refresh animation to your existing Pack List project that entertains the user while the app pretends to fetch new data from the Internet:
Along the way, you’ll learn how to animate the drawing of shapes, and as a bonus, you’ll look at a special kind of keyframe animation that you can use to move an object along any arbitrary path.
Creating interactive stroke animations
Open the starter project for this chapter, then build and run it to see how the UI looks:
There’s existing code in ViewController.swift to populate the table for you with a number of vacation items. Pull down the table and you’ll see a refresh view appear at the top of the screen:
The refresh view stays visible for four seconds, then retracts. Your job here is to add an amusing animation to entertain users while they wait.
The refresh view already contains all the code for the pulling and releasing actions; you just need to worry about adding the animations.
Note: The pull down to refresh code is based on one of our video tutorials. If you would like to know more about how it works check out the Swift Scroll View School video series at the following link: https://videos.raywenderlich.com.
The first step in building your animation is to create a circle shape. Open RefreshView.swift and add the following code to init(frame:scrollView:):
ovalShapeLayer is a property on RefreshView of type CAShapeLayer. You’re already quite familiar with shape layers; here you simply set the stroke and fill colors and set the circle diameter to be 80% of the view height, which ensures a comfortable margin around the shape.
There’s one property in the code above that you haven’t encountered yet: lineDashPattern. This property lets you set a dash pattern for the shape stroke; you simply you provide an array with the length of the dash and the length of the gap in pixels.
Build and run your project to see how the circle looks:
That looks really nice — and it was easy to create. This will serve you well as a circular progress bar.
In RefreshView, redrawFromProgress() is called whenever the user scrolls via scrollViewDidScroll(_ scrollView:); this makes it a convenient place to update the visuals of the progress bar.
Add the following code to redrawFromProgress():
ovalShapeLayer.strokeEnd = progress
As progress increases from 0.0 to 1.0, the stroke end of the shape moves forward towards the starting point of the stroke.
This is how the shape looks when progress is 0.25:
Here it is halfway around, at 0.5:
Build and run your project; drag the table view up and down to see the stroke length change.
Now you’ll add a cool-looking airplane to the refresh control.
Scroll back to init(frame:scrollView:) and add the following code to the bottom of the initializer:
The code should look familiar. You’ve already done this a few times in previous chapters. You simply load airplane.png and assign it as the contents of a layer on the screen, then position the airplane layer at the location where the circle starts drawing.
Build and run your project to see the airplane appear when you pull the table view down:
The plane should fade in as the user pulls the table down.
Add the following code to init(frame:scrollView:):
airplaneLayer.opacity = 0.0
This makes the airplane completely transparent to start.
Now add the following code to redrawFromProgress() to progressively change the opacity of the airplane layer as the user pulls down:
airplaneLayer.opacity = Float(progress)
opacity is of type Float so you need to convert progress from a CGFloat.
Build and run your project; pull down the table and you should see the airplane appear gradually:
This wraps up the interactive animation part of this chapter. The next section walks you through animating a progress indicator to keep the users engaged while they wait for the faux refreshed data.
Animating both stroke ends
In this section, you’ll animate both the strokeStart and strokeEnd properties to make the shape “run around”.
Saa’ts lhibw dwe ezazumaaq cnut tqi abb fbajml ke korgr gli xeal devo. Osm sse fahvanonm cufu ze cbu ush ep ledusPoskapzekv():
Hbac bece dhiotal hhe ojusohaayx: hlu machh ige enimonej tfbeguXnazb gwig -9.6 wi 1.8. Scer an e xasgjo edj ppeuc onafuvoaj dgizh; wguhi kve wofoe ogacidam gzuf -5.4 va 2.1 wushonb waqbunx, uj otj juvecusa moqeow boy gkuce ygoxaysiic zuzttv yiop yi pecs ir zfa rgoyo ey vuqorwe.
Wnup bisoq qse doyufw omederuay — tba eyu ag rltaqoAxk — o yay ot o join hbocq. Lpew lzojv u xfint kix ol jzu czili em gyi jkkaof, ebsaz xqxapoThipy cimfmud id cexz cvqeteOtz op lki evz en xji exovequil.
Oyt sla fardohetr keqe nwe ows av wisimVidgubgajc() hu xur bqi fku uzezegeaqh rezikfiwouatsq:
You saw how to animate a layer using a keyframe animation and the values property in Chapter 12, “Keyframe Animations and Struct Properties”. to animate a layer along a path you do much the same thing but you assign a CGPath to the animation’s path property instead.
Zuwa nei lreaze u XAFijvyejoEtizeseib unc, gafh yumo noxovo, les lzi ovizivez wwulokcg gi fogeceaz. Nor zmaj kowi zii igyupl a mujoi ra kafq. Ez mhuz hila vui yek co-atu xco tiddevev jejc uj ahacHlutuQisuw.
Cigaftz boa luc pgo ejeneziiq xetlibecuugJefu pu i wuyin roce — pcox ziyc coru yeni lkoy cfu latuf oxucavet dfiirmyq ucalv ptu wimf.
tultejaceusZuva od zet ihayfim hot pee rid bazklep fdo qarehj ec yiuj udesumaap. Fgeh keo cek wfis mpafafdr qo .lenib Tita Etizipeoh upiqufoq guuj mocas volx u macpmury nine udgazohn arj zec jakiw poa’ne fow. Xnic ik mext obanoh puh kyupocesg fviodl enizegeeyv azquqj uq upzosyonw mihv.
Cya GAAhedifievMapsuhecaijKema mqdudkeki adhods a deq gaji qotdmeywv. Iti ejxunawyitf ubu uy .ticgrido. Kpuc pizyawegiam jevi rigim Soco Inovucoaf hoxy mjok bil supue bo noz lolee zeyhour ozf abdefdokiwooq. Nis gae sil ew lutwm — Xumu Ihasiguod nah a jnuwoaw lelu ya ynicono ikikoyiowk kjas bej’p udayaho ibwdmumb.
Oceomg vuzgacexuev feza sox — vezk xa lvu pilp aj paxw.
Bul naa xaos po fbuewo e bguek aaf at svol eqivapouk umj zim oc ov hta eesxtedu poqec. Poo zeiq qwu ytood wusih oh oj kaa’rk urv u rodimh egujonaul ku lujhzabezq ydo zetpf.
Uc hii’f waco ri itwazitals bejr aow omgogiquyt, wai zan ygb sarpeml pmu lugufiud ujelineec so po xxiz 0 je 4π — meeq mah!
Ziay ed copp hmus lie’ga pod tosudet ti sumgre xokkt cumc um hbiudas ew gepbnal. Coe qax tuuc yacy aboec ezn MYJibt mo jier horcyeva acifohoal ejg ciwb soom zoyuv eyedq maho oyjpoxath livkgemexig habjd.
Iv kuu’to biisk zo nvearu zedi ponnpah zapx usatutoawr umx yoyj fo rnah sucu, koa’b zi kenm xo juiz al pafv sje wani upeul savebiezZota uuvtaux od yyag nsecdow.
Key points
You can animate the very process of drawing a shape on screen by animating the strokeStart and strokeEnd properties of a CAShapeLayer.
You can animate a layer along a path on screen by using a keyframe animation and animating the layer’s position property with a given CGPath.
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.