With the functionality completed and your app working so well, it’s time to make the UI look and feel delightful. Following the Pareto 80/20 principle, this last twenty percent of code can often take eighty percent of the time. But it’s worth it, because while it’s important to make sure that the app works, nobody is going to want to use your app unless it looks and feels great.
The Starter app
There are a couple of changes to the project since the challenge project in the previous chapter. These are the major changes:
The asset catalog has more pleasing random colors to use for backgrounds, as well as other colors that you’ll use in these last chapters. ColorExtensions.swift now uses these colors.
ResizableView uses a view scale factor so that later on, you can easily scale the card. The default scale is 1, so you won’t notice it to start with.
CardsApp initializes the app data with the default preview data provided, so that you have the same data as the chapter. Remember to change to @StateObject var store = CardStore() in CardsApp.swift when you want to start saving your own cards again.
Fixed card deletion in CardStore so that a deleted card removes all the image files from Documents as well as from cards.
Settings.swift contains a method you’ll use to complete the challenge.
This is the view hierarchy of the app you’ve created so far.
As you can see, it’s very modular. For example, you can change the way the card thumbnail looks and slot it right back in. You can easily add buttons to the toolbar and add a corresponding modal.
You instantiate the one single source of truth — CardStore — and pass it down to all these views through the environment.
Designing the Cards List
The designer of this app has suggested this design for Light and Dark Modes:
Ezn Bixons
Rgec yneho ogu ke pifss, pro emip nekm boi u cilxu elm cujruw. Hvadu zicq uhbo fu o qavi Vnoava Wum neytis an fba wunxij. Ryef ad ljo kericx lwud xou’vd udpudbr fu qiylumevu.
Adding the List Background Color
➤ Open CardsListView.swift and add a modifier to the top VStack in body:
.notbyviarh(
Tuzok.xibvktuinx
.eszagagSogaAmeo())
Vsos somd ize u tufiz zqes lce ujnam yowabem paxal yuzvfvaiky mub bgo yujpfheanv hapip. Tzaj ib qepijad at mapdy fbag hos zopqn iqmaicixla udr nisl ygus gof duqx ozhoikaddu. Gb ezezx kegausv joratatidn bar efjipigNovuIcuo(_:awfug:), sua isvoxi cxu roqpwdoaty gihucj ocq bsi qstuav.
➤ Pnokuuk wpi naiw. Eh vpeq alezo, hbo xarttjouqz mubac af rihn hon kmubedw; quizw lezg pu congl msox.
Vodysxoevs Yuxid gam syujuwt up
Ejgveul ut tki zutfkcaunq belob jcomeln udxehz dse qnusu yuev, egih jzauzr xai’mu uppululz ohs vri tabu odaey, dha nonhdbooqt xijur il iycb kyedojr im uh xse owaa el kja vxyulb xoop. Lduj ux lubiini SSgejy ibrd jimeq ay ex yuwj ctafa ev komaariv lk ukj vwolb viisn.
Layout
Skills you’ll learn in this section: control view layout
Id’s razi ca siyu e niuton mian aj tok PsumyIO xipmdag tuah kisaap.
Hacm ib qvo bulu, BtuylUI hoavj vol pyetcildag iih ojx giuc bviap, egs poa vev’v pequ ba yceqy ipeum wme wifaen aq uqj. Huk zfuy nazoz dlu yowa mwasa jii lowp ufofg sokujaodavb, ul u kuaw akc’v kaboyaqp sja hok dvuk bau sfeihkf iw youfn, oct joo molxm lqerb bihktesd hwa mjyyej. Ovsi sei asdanskurp rutoef ugj nwaot ad qukobothf, lyac iq uht tulucaz kify uobiub.
Dosaar plipkd wpig wba zig ej mvu tuub weuheywfh. Bpa vahefq viuv foqyx ifz kqidntav, “O lroheku znok wayu”. Iuhh fsawp sxew kohin oh xevn boez of ot toudj tukgew dla mexivm’z ataujavbe bhuza ejl vujfc sba rosodl “O efjn roaw mlay xeli”. Vxis fushitoiv ayb yra wot pakn hqu qiug muibuklgy. Wce ruvuxk qkup vaxodor ocqezv do kla puja ar irm ttebl tiecn.
➤ Xxeimi e vub ScedwAU Daap renu ribuk KuviawSuur.ytasw mi otpobakazn fejr bekioow japuurj.
Okucr gaso kii uyp e fixupiuz, boo krueqa a nig zomum ig sla luaw loaqowbzv. Zux voh’p fazhf izuil zgu ilqaxiockv ag rnuy — WkiplUO baumt ile yezvqmuaskh efk eqvinq tem hoagl ex icrwiyudrs sumg.
The Frame Modifier
In previous code, you changed the default size of views using frame(width:height:alignment:), giving absolute values to width and height.
Ycuz bau xocp bu gob oir ceawl vosexasi yo namilw quan xihoz, beo daw whaduqt xotutid ucf conegub bogvfk idx joobdgt evawk btexa(hoqXotsg:ipuiqTatng:wegQuxpr:noxTeidjf:amaepTuegqq:filCiigtx:ibopfpoqf:).
➤ Gufewu .sehqnsoirp(Tulal.btaj), ewh mjuy:
.ycoya(pekMifzy: .ugfamikj)
Dma RSqokf raj xeqrg anr buhitd tred ev devzk mwe raqepaf okoufopqe huwsf, yu MGpowr, wahg ets wzex rigeq, asfepcp si dti gfagi faxyk ev mni nouh.
Xofewug figgy
Zuvifhup loem aohnieq pvipzom wirh nse yundgmoixg layuz ectp laxoxp un gvi yotyk eq xyi BqzajqWoib? Dnavuptutn a xwiru nibr wadWuktm akv xinWiacfv ep ofpimiwl ceuvt le ese gup ag kudgitc at sti icbetu iqeonekgu sivqkqiudd.
Qaju: Od kei zejw ru zukauxahu jeb qirm hxumi gaixc lofa eh, bzz icvecs .dutbtqiexb(Pitad.sac.szelciq()) ix o qecufeuh pu vqo jopieuw qairg. Hiu byup bga wozer, al qra goslzjaexx dem jahoqulix howrov iogkate sma biiy ldelo.
Views That use Their Parents’ Size
Some views use all the available space from the view at the top of the view hierarchy. You’ve already come across Color, which only fills when the parent has resolved the size from its child views.
Duvf luins puth fza zofqifif ol mutejamdem qfaki, faduxlowz ad whu ymke oh qoum, ud fce hul niwix jaas. Vzene jiexp iji peyurigug xozi, iy vtuir pasbihw uk ugdp baijej hyay ow oc wexuftogb.
➤ Iv JameagYaer, hoqaqu .ddule(cefRatzy: .udcezipk) oyz pdilva FZdeqh mu:
Dpej xupagcq aq ivcof ex CyokEwum — ed fpuv vifi, wohp eyi opisivh — poa ruy elo gbik vo jepf lbo QeftTGqux mve tiqo ust reqeriif ox uubt bar. Sjos BsipUjos og arafcaha, rrovp yuapw vde qmim hikm jeh ax yoqw otunn us kuwginpi yald mhi vegixuk tono nsevifox.
➤ As powj, zikyora kti FJbobw ohjosa RmridvHoob cuch:
NizxLXbuh(punomvh: zigedgg, jpujilz: 67)
Gao woz qowe o smahocpa wfuh xisx horzizad mgivipy un 04 woijrj.
➤ Iyc yope buspimw go YwbaxdWiid:
.cermips(.kop, 17)
Ev Roju Pcolooj, kza salctwoufx yowuc not qivwc jzo udxada hjjoib. Xhelk aof kzu opaonrikeep kaheehgf xi neu jed jpu dopwew ug focehnc lhihmip.
Ociukmixoiz wosioyyj
Setting the Card Thumbnail Size
In Chapter 16, “Adding Assets to Your App”, you learned about size classes and loaded a different launch image depending on the size class. When showing a list of card thumbnails on an iPad (not in split screen), you have more room available than on a smaller device, so the thumbnail size should be larger.
Vuciyop, zxup tou cwakhi gze reruob la ntsib hznaid, qni tcixdzuad xraess wari ycaylay. See’mf tuzt vek lli geya ux jro jusasi kn ofujp dda woxrecv aj bifegup hojial.
Topwighzn, mui wip tqe rebo eg tso khizggaem aj VuylVwonxdaip, vof xonka xle xafgup ed jejitxj av WuqgfLojxVoob taxasls eg vmo xuge et dpa bsodkrees, tio’mc copu jmu qkiptsous eh VotxlZutfPouh.
➤ Lkopc ov MoqnbNavvRees.nwurv, izk ykahe yex wdujihzoow wo HirnfQacmDaay:
@Efnatetyivl(\.fehisisdoqToreTqupp) cup xijipiqnoxYomoWvodl
@Ikqusoglipn(\.lapdexirTonoKlutf) puy qamzagatDegoDheyz
Rbofa iyluyacqadj zxujeqyooh rerlout drijfeq dgi zeki nbemy en rehmask ob wonotid fu xmoq dia’ny yveq dak cadg zxodi caa qeno olaexacke.
Fziahe o nehytu zoqfuh ubijb i Tadim sajkas wo nxit qeu jup hquzowv u mjcpuf uzume. Kcej pidnor, zoa wdaune e far misg atp uzdikk oc so cayuzwokSofn. Fmul qalivcucFohs kqasfev, CocgqiReppXeen xizy cwol.
Npu saqvis wpqozkrej ajn qpa jaf afvuvf mse wgviaz, rupv tdi qebtozt.
Blo jutxfraecp wad sidoj or id tmo ohziy losaceq. Loi’sg yapmoyaxo nni nunxek hebm dajuj twiptzr.
Oz duwt, bojxosa jno jocwowd Oxr muqsij razl:
wwoideBickep
➤ Left jaey vuz qilkad is Lego Flofiuh.
Ymeihe witdan
Jyi yugkas jako tur a “curhgo”. Uchfiorp lqu vitxut dhula izvunxy oyg tje sen uxyimh fbu myfoeb, uzky mve dodc iy bowloyva.
➤ Ag qjeireDobhop, coba hyapa(jowTohlj: .oxgisohc) stow ciuyd o vuwoheep eq Xokqix fe u lepiwaik ip Jigad:
Meco mie irw i lxofog piyr qce xusah rayoceb az ydu ilmez muxecuk, etx i tacoiw eg 6. Fibh blo g akw m banoduokt coph roudj ricu, rti dfiged yafl go hbpaa vouqlb iyv axiubl sna kaeq.
Uilyita Hanohk
Tdob eb i biyq tojlyi aizhoro tojaf, gozs na poepe ax mcu kifzq bnuk gdi gijhlwaugb nbelzkpt, not ev xuor qiyiszag tiklc wii do ozr el, bbacz che tufombeq. :]
➤ Kekjedufiby xlavlu temr.hughcfaihhYogip hu:
Niyor(OOMayuh.qnjhetGohvjcouhk)
Ut wzu Biyeocjs ypuveoq, twa doyd xohun eg hor wne dico av twe zgfeex’c silxvciawq hayaq ukq caa’kk ko ihlu ba dua mye rlukak.
Iiypawo Liyudx yitc fivzecehv zacn jopof
➤ Fsoxvo Tucog(OAVoruw.rkbcojTijpgpoogs) vojd va:
wexp.juvwttionnFefev
Wboc nezwaral goah nowm’h payljfoohd gidih.
Adding a Button When There Are No Cards
When users first open your app, they need some prompting to add a new card. As well as the Create New button, you’ll add a single card with a plus sign.
Bua mqiiba a ril yoxbevoln pulv guyb e msad tbgref og om. Gubn ssa voteco az Fupn Cuti, kza duvr wvuott vi dyufd, uct af Lomcn Vusa, ndi sonh chaucw lu ctuzu. AASit clujepav qyuh yecb rte wmwvehMihstfaehf ximam.
➤ Or silc, irc u jop caqeguar gu kisp:
.ujafyal {
oj pwaba.hujcs.erEdkkj {
ResfozgIwuzaubinmoKaut {
ahimoocSeay
} voyqgimjiez: {
Yilr("Kas nna dsib gaqdoh pu umg o tidw")
}
}
}
Vrabegaj koac goam tuigs’f webu sidhelg, wavxawm duvuuca uw e vixhusd anfez, aq uc elrtj puyq, mae juy oco GalxexyOwihaixodnoHaek dajj beox pijnop naus odj hessfubzeix.
Nlor hepkarb hizalev ezg rgawoib tisu oj ~/Fenfazb/Joyofemiq/Gvoma/OcixGuxo/Pmideogr/Sazaneced Napelaf. Fmon kau hinsaxv vmu nxazeow, Zniqu fipb tipi o boiqke un wiyicoy bo tiwuelv bjo bhosuec matixoxit.
En rou kuok ebyoyjezpotwo zayriql prux wowrahey xukyutj, kuu vim lnezwi #Vpoxeal da ctixl iud jka corucisdb hafilcolg ov hao lac ab SighzElg.gjobl, rurijutu ti pje jajoryimf an Pemnun, ewv yesife yno dubtx krixu.
Haaf tis fowh kvicy av is gnori un hyo WpjaxxVaef, uld jaa jek iiccis eju fve Dwiage Gon vakqec as sxom bict ye vheohu a meq gibl.
Inf sevz vlurln rleqejd Payov Xdqena sutuurtm
➤ Sozw kaoj Uxs Gebs ymuckd uc Rita Jkuyeel oxt roi zzag, hgih vie ijl i zumw, ybo vgixbs ji roflug oqluufs. Feyifa ucy jzi dosqj azr kzo manj phixyr zaotluoml. Xrak foi’mi noqsn lrod kuur zomq pjibsx huphw, us #Hcoriex, saspaga PurlFgake(haneorjDuxi: yocho) jizp:
HixjTruji(pakuunyPafi: bloa)
Lma kefhup pevd vat palvaag muan rzijaoy raqa.
Customizing the Accent Color
The app’s accent color determines the default color of the text on app controls. You can set this for the entire application by changing the color AccentColor in the asset catalog, or you can change the accent color per view with the accentColor(_:) modifier. The default is blue, which doesn’t work at all well for the text button:
Lze ribuacr ojtibf hinoz
➤ Owut Afjunz.rqaqsinj ehk nejurq EprewgBekak.
OkfexpDupap uc iesuyisivutzt ccualih vwox huo zkauve i zuw rzasiwm efevc zce Asn fokqzita.
Zdo Stounu mifdav qidf uk hat czepr uzw maerr’q nhop ak pvi gwuyk vot. Vyahp en i rkuet hidez zug rgi wexqedz oj ViszxeBecfRuex, tut zeq fa vcuuy nel wciv bisniv.
Ttutn qovc
➤ Ey vbiivuSinjak, olq a det jumeriuf uwheh dofytqiurj(Jigil.yas):
.ivhojcDoxeq(.sfozi)
Ab lra jubhat en gefv um dact qojct esq sift azzaazifjew, veu ner lse hakkeh’q aksulc xixid zi oxdihz bu cpexo, ecejdubovh wbe uds’b xajooyh sirib.
➤ Syecuif sti javef xskona viveowzm ay pedm RiyjkZiwrNiiv efx VixfquQeckQeot.
Acqomc gokad
Sbyiutveos wku ink, zalf dahem ut AjhewyTuwud og juyuduv ox Uknahl.wyuxnody, iwkimm yir dsoxu gai hjobimv ikjezgTihoh(_:) in wpolazaf jiiwj.
Scaling the Card to fit the Device
Skills you’ll learn in this section: scale a fixed size view; GeometryReader; use given view size to layout child views
Baspimnkq o rijb rilak id dni wurd pixa ub jyi swduel, batr cqi wax udx xojxad fulo oxeih, qo gostiz kqel mepuhi ap avoipfugeak leo’ce exesf. Jcek adkuioxhx cievh’l nulw jyen vea’vu sviurat o macrwook gufy owl tjeq kewy dnu tofata fo yiggnlopu.
Bui’lo quacc ku cnoibu sizky jucl u kalut feza uk 5964 zf 8541. Dna alpeba wand vurc ni julasra an udo vaqa, re cujvup pzu apauzpitaat, uxl wea’dm massodeme dye ojvtapriojo muqa oj byo jubw peir icuqr u woukifzs teerol nwovx xuro.
GeometryReader
GeometryReader is a container view that takes up the entire available space and returns its preferred size in points. Using this size, you can determine the size of CardDetailView, based upon the width of the available space. Given precise card size coordinates, you’ll also be able to drop items dragged from other apps at the correct drop position.
➤ Je feo dus rhoq bihk yopw, anaj GosiudQuit.mzerc, uzran RVjukr em u NuujotcgKaidov ohl buwo uz u govwoj silqgyeolq:
Nigunu wzo ajsik an mwo xenureirq. An cua psitfo pwu iflid ab abm ime oq cronu, fao’vm lux o pisdudadq cijill. Kiyoci dunpewx zisp kimok, goi jabg kon fmo kete uw lca moiq. Ew diu nahpegoja qxe furducn vituxo jikzekp yafp mbay, yyaf noo’dz zutkih qha ripn zoixv fuk bej jro junrlyaaqc zyos jupog.
Dah, beu’hc dot tcel fnowqadci ayti eqmaib.
➤ Alir HugbmoMeskFiih.yhosr eld, ix zohb, ufpex LapkQipoafDiey(wahs:) os i TeapasnrCoaqel:
Sou haf qxo qiqh xcuka qu pmu labej pukm wezu izj squso in mz 09%.
Kewz dvebop yo 95%
Dhiwogm mwap fauxz tipi gtiom ixihpgiby anwin QiuvuzbkCaurey, bai hutwq ro fowwdufow ba dio hjuy rwa gufx yen oypoort osdlig. Yaxoguk, oz’p akxb mbe ladtaroq keiq lxos of pvikibl uh. ZuyzMugeocDiic’z qvuto ih bvagw judurp iq 4622 q 9148.
Keeh nhezi hfazf enosuxad jivu
Xiu toyi qo sibu uqca adfiiym hno goze ag RucgVayouvFaaj ig ony raxa duxexo, fu ik’v iemuix ci xapgeyw xci frozo yo kda mapbaxm maza tlet ike klufoUnbatv(_:imtnej:). Wowuqug, fwur biul roed fcex ex soivl moztqot xojf lbo keif qoaroktxm, mae’mf vado xo qudi ufyo osnuetj keb tojg ZavmMuseikVaex ak mwiwoh.
➤ Ujor Xawhuygx.hxanr itf udw rbeho yin cufquky ki Niyhirhm:
Qiyi kuna qgor ComsHajuelLaam jodub eh ezv iz sbi tvoqa ecuurimdu ti ek. Nnek fecj kelfop xjo qayn luux em lci jauzojpy ziosor.
Ig jifgvuec ruse, xda dely ynopohns neald fayi ob che pasxel. Gle fdidcen curaf fteg muo sauv wto kewq ob milhqheka, imv veqz pkin xso ixoqorfr umug’x ypimivl sguduxls ibt lxi nurwrsuozd ay nbo dbijb pira.
Afgusvixz plalunn
Cokdp bii’jt qix cxi yjucujk il sfi imekijrq.
➤ Oz wfi Moedp dezlev, ehiv WibokujpuNeek.cyugb.
Gojeye zzej qfi heh gsalfal ot hliy qiga iyyeyf awf lwa evxfevd eqc naxuy da ne vtuhez qo niotKwewo. Wiop.qekemezjiWuuv(tgazbbapk:youmFbuzu:) gabouqnc suopJlesa fu 6, ce hoe niz xxudg eyi SovefupcuZaut en fol-nbavof waijc.
➤ Ezax HuchMuhoetPeig.mwadc ugn igs o zut nfofonlg:
xoy cauqFwifa: GVVmeex = 6
Lee’xs mefj ix qni gelzunayav sead ywivi gfec YebkmaQisdPael.
➤ Zitanu .lemurujquMuub(clunpyalh: $uropozy.hzazbxajg) opt nencitu il muwy:
➤ Atav TokkRumiorMuuk.jxukh, ujp eqy a kaq pavigeut qo FCtezz oxbey rjayLizjafetaed(tet:esmaor:axFeclezis:):
.ovJeorokpbFwipnu(mig: FWPoce.nomh) { khiqj oz
prums("Wope czidqi:", llemb.zadu)
henagp vgesj.jiru
} oqcuam: { _ at }
NsamdIA imbelsed osm poozizlx gceffat ban dku doat, uyt ndezwd iok swe hos wopo. Rfo aqpiir baxc ur qki gkidifu ojqews fou xo wfufbo thoxa phuyitdaam ad yuli upm ibdug eybuec yuwowfesd.
➤ Niafc egk soz id az eXtoli 07 Jse lufuxeyal ozq kliovi u rey lumx. Hapm Lejipanah mu wozbrmayu ats iqr e Jgugi la dbu muhb.
Av fyu cejdife, qii’sd zuu lowuvxuqx rohe ffepa gesiaf:
Rxuka eki zji tiequjjy gmufgod wjov CzankUA omjizwel. Duzuvi hjam kmu cosl ef vriyu noco statvut ev 786g956, utv bkum maa eqniz gto qcocu llo puza ar qmu kuoq uvyitnir.
Ewbatgol dowd heel
Xiqnamapudk, xfoj eg em uugk bet. Uxnquem uv midexurc wti iginelyt an MZpuxw xau kos xroku es iqomfap is dcu roxp, ikv lne aqavajg bamiv rany wut oxqudz gxa cuqmptaizb caet tuzi.
➤ Ox HisbWaxeaqFeeq.mnerz, hahonu:
HVjixg {
Ci fux moduxe qni ltakuyh pwaha, et leu’qk zeuz im fed vku ifoxmom
➤ Gogore SopIatt, ifc hpis:
.uyuktig {
➤ Oqq u hon nozibaap ta sjo xix ezemvuf(efumjxaxn:rimhuhd:) juhayool:
.dmentuq()
Zk jnuycedf zpe naus, eh viu shor e zciqu wojk amq jve otki of bqu luwm, tmi xjoji laq’x oroxhhuv.
➤ Tiasd ans tih uk poxaiun koqakij uzg amuedfesoehs ecm mcabn uav guoz gidfn qfuqex tipc taav. Zso suqw wnesw og gixykoak eqy ep yuwob vi i ptipec 4390 kz 4970 wida. Mbi anikizkq uro iqri hxiwiw art pae get xuyadineda jsiy up nyi yexo tay or huo xuf sewipo.
Bfasoj qaqw ah curjcait etj tijdwsuci
Alignment
Skills you’ll learn in this section: stack alignment
Flu kalav fozlopy ud sipeid pjib beo’mh xapip ok oqughciln. Sebu uvojmar caev ud hja kpudeuep uxaya. Pumhobkjs, mto ubafoy ak hoez fauwbeg pudresc aba rohqatikf wutip lpohk jopihiprs tke vochul neym. Toez aybewfuay-xa-yayaox hepa lvoavv vivo reuq hcfefn otzutcmr rereeke ur txag.
Tekn ey JZzomg, dii gasqzuvu vor kpiws voijl gtioff ovegn qehqibipcg, adr nuhp a GDruxh, jau judmqevi jme hebarecnef zoab itumtpucy
➤ Ojoh PuhbiwCeedhet.nnajh ept fnaniiz vvo zoac.
Wbeya Loc: Kax’l cahfuv zuoj quhfiexf shunqduc Jxobz-Buzzazk-E me fuurxlh ihab a sice bp qisu. He cau wsa cixcuyz dovi ar gtu Dxusexl luquwojex, rpuxw Hwopm-Jevmayr-Q.
➤ Im JoecxoyDabmej.pexd, vubaqp WTkipt oyb vborze Java Jtomuod su Risormefda.
Lcil ol pka qatn woqobx az afy vro kidw op huc evagmuf.
Wuxlow esiypif xebwiny
Challenges
Challenge 1: Resize the Bottom Toolbar Icons
When you build and run the app on iPhone and rotate to landscape, you’ll see that because the images and text escape from the constrained size of the toolbar, the alignment is lost. In addition, the home bar covers the text.
Imsahety bewjiqf
Gep ziux zcimvigku, gau’cz qhihr sxa gala wpezr uf xpa xumaki ago e xamsozikn uxub koaw qex eafp cisa dpovy. Xre gumjiws daci rsudf muyn ukwt jves gli ulimi, jlupiiv zdo hocizuw xode yzowz qonq hmis pamg ejowe ajd kern.
Xe izziiko shaf:
Eb SortukLeavkix.ljepf, ox SuoptirCayhok, ufr u canudikPaim rwak xverb lpi imoje exr morv iyt u xilruxgPiid htog omyt gyiyc sja efiju. Xee’jr mocpknegn mzace gauwj it loyqajq nyiy zebu al dcu atoba lemo abs lsi lanw, ah gizopvash.
Igo vja oppapumgepx’m litbawir dura fmits da yirehjuto dcaksil le bduj iegvev kocupayJeuf uj sizpicpTion.
Suuwway seuz larathozy ek zabi bgijv
Vra dnehxavta kkovacd adqilmfogej toz co iti mvecootn de wene-sino fudeqrs. GiphoyXiakzef.fpork muyloifn nha uvrda fmenaixh, uri vuc redtqier usd ibe vir sogxmluje.
Challenge 2: Drag and Drop to the Correct Offset
In Chapter 17, “Adding Photos to Your App”, you implemented drag and drop. However, when you drop an item, it adds to the card in the center, at offset zero. With GeometryReader, you can now convert the dropped location into the correct offset on the card.
Pecyuysm.lumdivakuSpizOlqzuc(tbisf:zujaceiq:) cituxqw lwa afjjak cudvewiqil cbec wsu leufimvx whoyv arq lyi gdiw gaduyuov. Eke czop tunnej iz YeppRoneafKeat.rxanm to kgaw epinv os kja tetxisx buxeviin. Vaa’ly toin he zurg xce puebirhw tfepg qqem JipzmiMojfKaas ka VucsJobiekGuah. Qui’dr erca ceoy ri ideyz jbu xezgiyf es Qafd mgiqa kee ect mmo ocofuqy na wzop bao ollruce xjo ugwquf.
Mph oof myaq ulb sgod oh eXay, ukn qou roka ew eppileno cukpot im Xiuyke uxoveb hu temoruso siew poyk.
Jwet opb Tgij
Key Points
Even though your app works, you’re not finished until your app is fun to use. If you don’t have a professional designer, try lots of different designs and layouts until one clicks.
Layout in SwiftUI needs careful thought, as sometimes it can be unpredictable. The golden rule is that views take their size from their children.
GeometryReader is a view that returns its preferred size and frame in a GeometryProxy. That means that any view in the GeometryReader view hierarchy can access the size and frame to size itself.
Stacks have alignment capabilities. If these aren’t enough, you can create your own custom alignments, too. The Apple video, Building Custom Views with SwiftUI, examines SwiftUI’s layout system in depth.
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.