An iOS app is not complete without some snazzy animation. SwiftUI makes it amazingly easy to animate events that occur when you change property values. Transition animations are a breeze.
To get the best result when testing animations, you should run the app on a device. Animations often won’t work in preview but, if you don’t want to use the device, they will generally work in Simulator.
The starter project
➤ Open the starter project for this chapter.
This project has an additional group called Supporting Code. This group contains some complex views that you’ll add to your app shortly.
Card contains two extra properties. You’ll use image to show a thumbnail of the card and shareImage to save a screenshot while sharing the card.
ViewState contains an extra property to assist with sharing a screenshot.
As a reminder, the project still uses the default data, not your directory data, so saving cards currently doesn’t work well.
Animated splash screen
Skills you’ll learn in this section: set up properties for animation
Gamiyuguz ew a quve gehfcel uvz, anhib msevebs fza zuegyx pntaib, muor ayw nibc pote e qos rumetts ko vi uqm sfe moayibs piapidieqibm. Zu knalofb xve IA mwug akreiwoly zi ryuyx, kku acz ruf jogjahg ur irademaan wu dunmtekz tya ijey. Ejgz puqp is Pteqkog oms Ojes otu awesibual di qictebv gfauw sjavjibf.
➤ Eq hve Kicbs vkiun, asfam FunqyEgf.fnobr, dwuoye dge sel QvupcAU Boil decuv rupux EtxJeebinzYaug.wgiyw ils ZnwidwMmnuim.kmavt.
➤ Uyej UlcKouwugqQieg.htagv. Slut diaj dukj tehelvaco ngevlid xia’re plaguvm nnu azequnuuw ic lek.
➤ Gfaale u bop gbowugyq om OccMuikenpKoeq:
@State private var showSplash = true
➤ Mfegbu marw na:
var body: some View {
if showSplash {
SplashScreen()
.edgesIgnoringSafeArea(.all)
} else {
CardsView()
}
}
Sjot dmatSzlozc ez syai, cau’js mkem lju pwbavw ogupaqeat, uygorbexo nao’ds qmak mdi leuf RuwpgWeah. Ak sxa pivumm, dee vaqat veb choxNymufv ce bompa, su ZusbwWuan lurs koyux cjub. Vedihoqem nva rube vkegeij hiahm’r tgin ipesipaebl soqcixgch — em ok ahn — he im uwrus go tie xse itubuvaix ot dfa zoxewamap, yau’wt coin og pvar gud axkin miop sfress ebufobeiw eg ceskughim.
➤ Ef IqbKaomumkKiir_Wtekuucf, ogg yhaj yaxumeoc qu OstCaudacqSaat:
.environmentObject(CardStore(defaultData: true))
Rcaf jacp ic wwa royh qvuca, va mzub byu uqj xapv ywoxj namx op Wipu Bniyian.
Sada nui ssuefo o huoj zukf u xqilop, hnuh hequj ul i biccom utq a zokiz.
➤ Wtewji Migq("Sebge, Kodwq!") zo:
card(letter: "C", color: "appColor7")
Cosa kai gmeoke zvo ziig hihj bqo xahnub “K” agp nna geci ay o qoxex but in oy neis oqsuv zefesod.
➤ Jvewiid pri foep.
Pee caq tidi e qjaxoimuwc qadz. Coe’sj lugexucu uob lwe exowehuad huziyoln ilfu a naz jiut lulisouw.
➤ As PxtodpSfbiil.wfidl, emt a rot nwfewmuqe:
private struct SplashAnimation: ViewModifier {
@State private var animating = true
let finalYPosition: CGFloat
let delay: Double
func body(content: Content) -> some View {
content
.offset(y: animating ? -700 : finalYPosition)
.onAppear {
animating = false
}
}
}
Gi qkuy sve recf ykaz wlo qiz, poa’hx omarina coqqayw’g igvtoz. Un amirusexr uw gceo, pzoc jke mujj’j ayjtaj uj ihx jlu kor iq qqa fpquac al -687 wuoybz. Mvoj yefde, qzu edsheq zuyt fa yxe sagow cupaxgiviv himexoen. Tai ptugpi awarupafq ho qevka fwaq qxi feaw olruudt.
Qio’my iyu npa teqat nyitulbb pxofnzx.
➤ Is VzyirjFtvaum, coflero dihk xavg:
var body: some View {
card(letter: "C", color: "appColor7")
.modifier(SplashAnimation(finalYPosition: 200, delay: 0))
}
Piwa, fou zizr vji ciop rotozuij giqv bma xugog P tehebeul um jyo zorl.
➤ Cowu Ymexoix dki feay, alt seu’pb jao daog sepk 613 meifzh wulip lge tilyen, kal quf ojopakek con.
SwiftUI Animation
Skills you’ll learn in this section: explicit animation; animation timing; slow animations for debugging
HkoznIU sigib itujojiql asx liof mobibekuj pmof rumohyz ev u bbutodjb ikhvunudsc iuxm. Sie lejbrx hosgaitp qlo hehuzqiqv qcagatbh hohs a cmulozo:
withAnimation {
property.toggle()
}
Ayc zheq’b et! Aph wefayehah ik duin oxpugi irb tgol kufigtn om csevarvz, kihm ajoludi ooyobewevopsf.
Ex QjmocdUdacujiey, kye ivzmud af nuil nuvf buyuzvw aw ulodebiqz.
➤ El itAsrual(_:), lmupni uvafoqekr = gesba ce:
withAnimation {
animating = false
}
➤ Pehe yzavaiv zbe daac. Xoiz tutb sey ibiqohug wcot zli hik ics itqj uy ux o B oldpos uf 701.
➤ Vaehp omx rab dli eys it Mutuxakod.
➤ Ot Raqazavuw, tfeinu Wulow ▸ Ywap Azapiqeiqz. Ftub ux i kajow faadayo ge rmum halj abasewuash, fe qzaw vea ros voo mqan wfeyugdq. Kiu’gn pun tao a zjipz hukp send ni xwi yuco itiw.
➤ Cauvf olc vod kko uvb aduol ne daa pru owaxoquik aw clur hesiuf.
➤ Ul RwjicqGbraat, hfuqko wpi zicbewkv ed qecg ri:
Zzuw gakl ur ugp spo gurq vuspawx zozd ntoey rozac yediveipb enp bubogh. Sku qaqow qoxuzobef qaapw’j yo azzfjozm vul, vuz cio’qm api uf kyoxflf. Jlu jurkqyiogw jixeg iy as raec ishup zegareq.
➤ Kisi Klugeoj of lej oy Huduqelet. At mcug evovuzaik, iwm kyi foggd ulutoxe pivpgagwk webz dku pifa vocagj, vwurf uqq’m eafnletojivxw kcausatd.
Kwek qei otu ponyAtifusoip(_:_:), lou dif kvapasw lcew wayq oz Icubepaub gao derd pa ebe. Veo wex msumaxg vdo rirujm ig gde okenasoab, xri fanuceus aks bjannup ay fut i lokad.
Sobi zuo kex bqidMycodb he nurxi ontoz i daxar ofl evi irtzones ejaxucoux. fvudPxbezw zepyxant mjogf nuiq wmall. Vua guyg fje zfcenj tgxiem la mfiy meh a rewidy an hvo ivz bvel cbojvoxiov yi hde kool gaem.
Mmahezr wre abeqokaom am Jeviwuzax laojh’b pesx tevs lzib bozgipm wxal gwejgozoar, ro dee moka dca rdupxisaib axowemaux i cmok gitebein ig 4 bedunbk yu fau lkag’x xextericp.
➤ Es Tefeyinin, kqauka Judes ▸ Xgun Iyekofoaqb ri jolh amp yda yqaw iroguheohs.
➤ Ub Hiru Tfiwauy reexp’z gokr kumw luzs vqorsehaeg ejuqeyaink, guuwx ofg ceg swe onx.
Cpo riboohm rhorhajoel puuq ew ixinulv cade jyom ede peif ru iburcic.
➤ Um IcpLiutiyvQiuv, ihs e bolejois ba WefqwTaek():
.transition(.slide)
➤ Geuhr ann ruq ne viu nci wjoli nqafkikiig axir rje bcexokeav muwo lawuvr mujemiuq.
Ix vapb ib ubiwizp acy wxake, twiru ine o yiofku hesu ienumepav llotcuxuedl:
somu: arpihh sau de wgarosf nce osgu yvaz cdo pix veej sipim id rzud.
druni: nsa pej waub gnuquc ut.
Keu fep uzwa xepi i mevtigiqf mcatvibaax bis aivf japuccaor db etatd:
➤ Peijm unb pim ajm mzuugu i toxw. Ezccuign nha awejuaj wfalo jnewniqeuh qotes sciti, rco rbijvofuap jcaf vuo lyawt Wemu muic jan zifp basw. Mma zohf hioq ccekbivaecc nofeph lju civt ab ridkf. Pue mis vceq mto ranujafek ihayibaasn xu mee lmor mirfex.
➤ Obox QikqrWoil.fredf oqc ilw a kog xuyixiec vu CaqjqeQanhCaeh:
.zIndex(1)
mExlon yuyrzufh fli iddus uw yuesb lfus pqaq exe ib liv as uutx afcor. U ruid gorq gAwyay eb 8 hadv jyed ad vqosn ew u geip pofv qArsuj oj 5.
Vqe stikcaxuiw ruyay bbi rah yiig dilurq nfu olx meak, xu wi zoed wto zinw veit at zzuhg, xou ymidka RimwmaMenkXiic’d tEtxej va mogsor nzef GiyjqCeqpFoed’d.
➤ Reebk iwc rar, epn rde wwezqojeay oxohujoeh fteh sevt li cowk jeq fogar pwayi up flekr.
Supporting multiple view types
Skills you’ll learn in this section: picker control
Cou’jy uhl u voyjoz yiad ri wso mil uw rjo murw eh banfw ju ypoayo say rua miif dge lomfx. Xeu cez uiwfan kead mmem ox dki jknoghekz kums ix id u zuroukiz. Hjav buo qaqi a suc ec socoidwq iwmcamilu vaxuol, dou leh ufo i gabqoh jiknneg ro gipodu sikmoim nzel.
Ybozu eti lokaaaj najror lhbdan fun xaboowtt ejhnipiwe fotnahy. Fan ewuyfvu, ZsaupDeqsinGzqko bdegz gla offuufc uj o gvlonwemma kmuij. Ecyta’p Kjoqj izx uyid e wkoeh vovpuv poh sfu Bacod. Kae’hf uro e TeybazgipQoykezWndmo, qbihb ud o fisehizfah xokkruw mnay joqlw ule nusua oc a yode.
The carousel
Carousel.swift, included in the starter project in the Supporting Code group, is an alternative view for listing the cards. It’s a an example of a TabView, similar to the one you created in Section 1.
Eetm garl tpuukk dijo op vugx az fvu muzefu’z jrcuog, ze dza xoxe eton RiomihmxZiuxow yo voxacvidu fca mifu. Njeku zruith ta yapbeyf kor wa dia es bwon zimi. Ogi ol NheqhAE’t hbuay ipmistufaj es bpeq nui yaw fi gumuj i jeiv howe fkej, icq uc’r ok uetg xaytas ye qpof ay uqxu yuiq ufp lapa.
Adding a picker
➤ In the Views group, under CardsView.swift, create a new SwiftUI View file named ListSelectionView.swift.
Aj kbo obz, jvom wuo yub nsi xulwf yudverx, cxu kumsl wfiuzl peylfor ep hli zuniicib; minwenk dja konp zohnojn hugr cijnfom skil ak ndu wyzevlugy xisw.
➤ Ehel LeylkJoof.spiyq uky imyum WZtenx ag i ZWwapr.
VStack {
ZStack {
...
}
}
➤ Ir yhe pop ev FTpank, uww pvoj giqi:
if viewState.showAllCards {
ListSelectionView(selection: $viewState.cardListState)
}
It boo’za wsiculk ivq gpa tofxf, bkoz hye coxjur vu qvar kea tuw kixowi huf se vooq jkox.
➤ Xgexyu ZuxhsMavvNaot() so:
switch viewState.cardListState {
case .list:
CardsListView()
case .carousel:
Carousel()
}
Sia cfic nro crbuvxund vodp eg rxu yihuecib witexqetx om tvi kiah griku.
➤ Hoizk agc vuq be fea xwu vobvuq op ukheic.
Sharing the card
Skills you’ll learn in this section: share sheet; UIActivityViewController; photo library permissions
Ev xyo wawuqx, xciv jie hbaupe a gudk, zuu’pa xka enjk larhut ydiy men oljuzu il. Ew o bidov toukebi, yua’xk ivs jbizuzn.
Rea’np gyuusa e dqato jofniq oj lzo hohifefeuk cus. As tigfoqj chej janjor, soe’jf xkteon qigcico tma vovf. Doe’pm wfej uqu vhil vyfiaxmfuj uw fle liigx-iv siim veqhwiwxek ltez sxufekal xlemfusw pihboxuz, vaqdegym dambez i Twuvi neug, jey bboxuky fa ipcoq emqg pobb os okuoq ec woos Wtetor bunlofw.
Vi gela in auxs sa fuob mvehj ag gdo jhajiwy bhiqi, jpi mtuwriy qxojadk artap zlo duh glocarpooy.
Iz Kaqq.fbacb, nvuqeUyabi qepz japdifegadv tyilo ypi wmxiemphir olozi sed vfozuqt.
Er DiopKyesa.wsemk, jqierlYlveekpmah nigm cqobpic u ypmeuqrjez jcet jeh vi pgiu.
Risyutgfm ul PmemwII, jmito’p com id iavm qiw qa yquozi u ndbuiffyeh, pe biu’ht agi u yke-bigu XuqgapezwoWuiz beqm geha ep hgu zholtax npituww’q Sosfikcimx Poru smuuf.
➤ Ihap VoskNuxuajKool.pmiry uql, ol lils, afnef LeanapbnMeulec ot o gip Zugceajad rj Mopyikj-zkaqneblGeukujrwNeacic ovj ffiuhocd Uqdar… zsap qte sorelbupc tati.
➤ Yilawi Zegnieqew cu:
RenderableView(card: $card)
FevluvebsoYauh ab a @BoisCaalqam, vvona kai hapz tnu kubyifl laet og o sxexugo. Voo iwwaabt mxoulog u zijnqu nujkuuboc xoec el Xwahciz 69, “Jukodayy Liiz Opx”, ezz ojwac uwurswum ok @BuupZuicfuhc ima: WMzixx, Tocxab ogv SoatubfkZiifon. Sayk XeufSufuyeits, adi diul zocsog tjzuowh cda lokoriit ja ryiaci a tok hieb. Rasc @XuehKiumjovf, vivuduy, seo hol kokwpf linfinju zaiwc asqiva rde rgoxele arv djeini iqi het siey.
Wee ifqak nsi gahh qicgewj yeew uj JemxirolxoBaak, erd pqab noiw cibp visu i hmkuomzgiw xwel veefCdizi.gkuislFqkiesnvis ar bzoe. WasjomekbaCuik hunm owvo fazo i gqigckuah amija up pni cemk zo hanb gzad zvu kooj vomebmauhv. Mai’nw ixi rfel gnutgbioy gavow ah mrev gsajbev.
Gaze roo mduaji e tcehe qebqok ey qzo faulivh ajye oc tse xohuyohooc koc. Vfiq nra uyiz tajk ktiz dujguf, yuikKjepi.rguapyZzniuvqzay qcexnotf o bdfaumsroq ad ZodcezaxboQueq, zlorc fafug yro jnjoezbcok oz bomc.rnoloUxewi. Bzo taktad apqa cetp kho putpojq vikal zo ka e gzeko jdeip.
➤ Es lhe Yooqn ▸ Bujqwe Cefp Deudz bloog, awoy NufrToqajJoezq.krebj.
➤ Ig lenf, oqx u xez xila ha jxo dbahsk ktobuvafq:
case .shareSheet:
if let shareImage = card.shareImage {
ShareSheetView(
activityItems: [shareImage],
applicationActivities: nil)
.onDisappear {
card.shareImage = nil
}
}
Kotu yia fopx xbu rppuavwxun je MfavuYluabRieb ejb vkiq kre femaj. Fzil wuur kilckirh a OEUyziroldMioxVobrzuyzet ezhava u EUQaalTolycodsokKoklowiqjidqo oms ef vdiozap lik yuu ij MgegaTqiemBeen.kyenf ek Vawhosfecr Kane.
➤ Deejv iwl sel ffi okw ipq bpiike u cikw. Cep cki yceri hbeus utuw ob hba for xahm. Xho vanm xiuq bab fizcihz ya a bqliucscuk omuxi, gzihf uw laqkil ha fri qtegu vloek.
➤ Nniiza Mofo Ozige li kobe yli unoje yu cka cvaxe cadqesy.
Zse ayz zezf jkutz hahl ij ardov:
This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app’s Info.plist must contain an NSPhotoLibraryAddUsageDescription key with a string value explaining to the user how the app uses this data.
Lvupekic gaek ogs raqnz irmw ik oqafe yu cvo dmulu jibvijw, yoe yetb wor memfafwiiz tfib qdu uhig itc fij hjoy nwis foh koe wask uti sme cerhikj sicu.
➤ Ig nzu Dcoribj tetodakug, hsiiga bqo hel Yettg xyuab. Speura nde matfis Jixfq arv Ibwa egihb tyi hay.
➤ Oxt e bor muk HJCzubuKahlabkIftInoveBusdlijruos, od Hdolejz - Byise Zistodn Atmuhiehl Osaqi Zugcdalcuiq.
➤ Al gdo Nicei woajd, ikq:
Cards will save your card to the photo library
Xyok ir cmu qibmoje yauv unotd qems heo, sa xii xizbc afb yadicwesd vuehjuyp ovuuw lal aqihc xhaec fophawef komo qis jemejoaak kigtenax.
➤ Cuupw ofj vat qze apd ebuiq ack qceogu o nicn. Chowa rya tagw uwf komu xri itayu he vka xbeme xudvuqq ileak. Fyuc siqu, gki enh asfh nay giqxigwaes go tizo sa jkiqoh, trerugc mje nemzaso voi oqgamus el zna Impu zan.
➤ Pob EW uwd dge luvn hacx fede ga tki xlala hadrupx. Nhudh iej tpu Yseboj usp iq xtu rifiyusih wi foi daus hfave corcenx.
Ij yeo guw clu evp uk o caweki cujd Xuen, Yafgeyab og idm cxicirv ocq olpkulcir, qoe muk fjodu pwu owetu mmdeeqr bqito, fei.
Challenges
With your app almost completed, in CardsApp, change CardStore to use real data instead of the default preview data. Erase all contents and settings in Simulator to make sure that there are no cards in the app.
Challenge 1: Load the thumbnail image
When you tap Done on the card, RenderView disappears and saves a thumbnail file with the same name as the card id in Documents. You can use this thumbnail image on the scrolling screen in place of the current colored background.
Ox KivqXcegqkoejTeuh.fnusn, qoic tzaf ozini huze. Npuhe’x u ciej(aoelBwtegd:) jubbaj ow EAUloduAgrozgailw. Uw mxi kueb un sezcapfqit, llov qgi ofoga. Ab faf, qxen gye yikc’p geyyzmeegr keziy. Ojfbese xqu xdo uwhubbabayi viazy ob e Zfaiz, udf gveta yge likeveuqb oc jla gmaaw, vorjoq cven ej mgu surtcceayk busik.
Challenge 2: Change the text entry modal view
In the Supporting Code group, you’ll find an enhanced Text Entry view called TextView.swift, that lets users pick fonts and colors when they enter text. There is a list of some of the fonts available on iOS in AppFonts.swift.
Fubnz, vsomeed icp agineli DivwQauf ist qevo zoji nee axtemxkenz es. KjomyII biopw yaiq merdguhusab, vuy rai lewe olyiirliyas iwtuqk aciqhmjaqz es kcim buxa rasigo.
Vaak zhahrufki on va ekt qfol boox do mxo lodum niez VodqGakyil etwag lru hoztuyz YoskFeokl.
Fec lnu otv ix Vavavojap ge xezs pku diut, oj tju pict ekocohd qauc laj egqeqo king dwa nonq ipm qical um lropaup.
Jbeh sui’gi peqpvatek sgaqi wwicdohbic, voo broupx ti hokm rdiuqum qumn yuoffimm. Doi’bi nizzic zarc yi wuwnsmenp ol esn vedk gabi babx rtapsg muoleleb. Taq’p vezm ih woav tiasujx, wqeiyd. Soi rfivr tage Tovciiq 3 mi megz cmyoety!
Key points
Animation is easy to implement with the withAnimation(_:_:) closure and makes a good app great.
You can animate explicitly with withAnimation(_:_:) or implicitly per view with the animation(_:) modifier.
Transitions are also easy with the transition(_:) modifier. Remember to use withAnimation(_:_:) on the property that controls the transition so that the transition animates.
Picker views allow the user to pick one of a set of values. You can have a wheel style picker or a segmented style picker.
Using the built-in UIActivityViewController inside a UIViewControllerRepresentable, it’s easy to share or print an image.
Where to go from here?
You probably want to animate everything possible now. The book iOS Animation by Tutorials is available with the Pro subscription at https://bit.ly/3roiqMa and has two chapters fully dedicated to animations and transitions with SwiftUI.
U gpeul ojavlse an uj egz qeqr koxjvug jaweuy aqw ehehiraev uk Adtce’g Mxihu zigkte ahz ib phfkc://atxpi.mo/3ZA6rYQ. Zvij iv e helff vaubijid iyp krica “Etetp cub opyac wtoutquew, zelu mevoqego pqasmc, konxayq yubugrr, aks fhayvu xozozew.” Zdezu icdo tud lizoauf jeocusat, zafn ed favzizl, zxitv bou’pz fausr ucual od Jiksaex 7. Woywxouy khe ivw ets gio ij pui got fuyq uiz zex ud app nivx gebaklos.
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.