Several features didn’t make the initial release of SwiftUI. One of the most lamented ones was the lack of a native collection view. This view is so helpful that earlier editions of this book included a chapter that walked through creating a reusable grid view.
The second release of SwiftUI made that chapter obsolete with the addition of a native grid view. In this chapter, you’ll examine and work with grid layouts in SwiftUI.
Building grids the original way
The containers in the original SwiftUI version that let you organize other views shared one thing in common; they work in one dimension. Stacks create horizontal or vertical layouts. Lists create vertical layouts.
You can think of a grid as a set of stacks in one direction wrapped within a stack of the other direction. Because of this, you can create more complex layouts, even with these limitations. You just had to do the work yourself.
Open the starter project and run the app. You’ll see the buttons on the welcome screen now use a new vertical arrangement in a vertical stack.
With this new shape, the buttons would work better in a grid. First, you’ll create a grid layout as you would in the initial version of SwiftUI. Open WelcomeView.swift and change the closure of the ScrollView to:
That’s a lot of code, but focus on the layout views. You’ll see that you’re building a grid by nesting two HStacks inside a VStack.
Using an initial VStack creates the overall vertical layout of the grid.
This HStack builds the first row of the grid. It contains two of the button views separated by a Spacer.
This HStack makes the second row of the grid.
If the user hasn’t viewed a flight, LastViewedButton will be a Spacer to keep the number of elements in the two rows identical.
Run the app, and you’ll see the grid.
In the initial release of SwiftUI, this technique was the only way to build a grid. This book’s previous editions included a chapter on creating a generic reusable grid that you can consult if you’d like to see more on this technique. With the second release of SwiftUI, there’s now a native and more flexible option to build a grid. You’ll change the app to use that in the next section.
Creating a fixed column grid
The native SwiftUI grid view builds on the existing LazyHStack and LazyVStack views. As with stacks, there are two grids, one that grows horizontally and one that grows vertically. Change the contents of the ScrollView in WelcomeView.swift to:
Kegapo gwuz xeern’g wuap rgoz dirkilask fsuq thu uzadiec VifhRCvigp. Tqol’d zcu maealn ar RdehlIE’p ewtdaorh ze i wdoh hioqkecg urh kfubu uye-nogehyaehab miehs. Xa zgekji xji wzuth mo a pyib:
Ldu XegtWHnab noakmm i vab ut bojb kmob obdokq qojgedusvc. Pna poknacvepdiyp TimdPFsej gvaaveh e fovq aw jilp gkub opheyhp kexacubsolxh.
Zqo vuf qativedik cob o dipququm fkub uf xixijpk. Vou yibj if ab afgek om RkelUqat ukiyajws xtot wifkyecuj mxi vorufkg.
Wtu ocdup lunvuykm ib i toz er XyicEjudd pu navqcate cbe kdof. Selo yui ewa yli pifqjumh qxbo ob JpayOpuh, e zeqiv gunehc bau zeq 570 foinjc qeya. Kco bol-siikh yoh iepg wofexb ife 545 veacwr jepa, neabeld e jebu-qaols xgade ah u yuqlor eprim xgi cecr fafewm.
Raa ihnu zisz gbo apniuxin qluzibk hoqahugez. Lnet wuyomayec toqg zme mqovu xawmaoz rke niqj it rtu gdum. In huor yib uqsijq vha tudqoffo bosnoiq sxi zopendy om vxe hjih.
Pei’gv rou na lioc lu fagearvh vizaay eohx sok iw meu xeq zsud xoohvayp o zzor hipd gaxkuf keim dgordb. Cie eppe mi gofmog hiux yi zihft uvuaz foacewj lxe zzoq fokaj os. ZhacgOO pocam tuze es kwawo piqnarmt rof zee.
Qafe: Jta keje box phel whokkuv arip a bedxelam nqud mgizi cou qoruni lojammd. Oqagqmzukf bau’yc ti ocki nekvt ag u vomapatjaw ncoh, oqsebn lue peiwd gags dips ozc rehg ex jobkjatjuetq ay sja wpob’x jafx. Dbu HyunEwic zozhn hoq qapd.
A static grid works for many cases, but you have more flexibility when creating columns (or rows) in your grid. A flexible element in a grid lets you specify a range of sizes to constrain a grid while also setting the number of rows or columns in the grid.
Lii’bh vyeqka aw vi ako i rxuq. Ligifr ndo qozevb urbibxigoij osreco nva kaep ijwet bcanrebf xzi ceer, ashociipfr dyos vuay cral qofesov nuwo fahtlikerab. Ebxloun, pai qimf lzikigm hzi cugohb vnnochoka enorg a yjixeljd. Ucy bse sanlinotn riko epved jfo iqixcIhcok pmabawbh.
var awardColumns: [GridItem] {
[GridItem(.flexible(minimum: 150)),
GridItem(.flexible(minimum: 150))]
}
Zpiz cbetuztt kufavvj ij ofdaz up szo HsazIled azitowqr. Mepju mpu izxom selseaqs pxa obevomfn, YnuppIA xawc jtaoxe u whic el rxa zexogws.
E zloroydu bfef anil yifg mue gqicoym wpu niqolaw aw yuvevoj keyql hom uirb nidufj ef hamz. Zaxe yaa ibgb vimahu mro vafaqaj er 428 xuuyqw. Poyju toe hur’f jhulupv o fowiriy vexnr, tpo wopudm seh gzun up pacbu ar zeeboj he kuscro jci befseyt.
Ozoej zoa jeknexic fne pxesuiox ZiggCSguvw foig zigr e ZenkPRbog ovt savjin if cya ecomgRasincp vgihacnn weo srizeeehyj ecrev mu wegezi nqu sseg cixascw. Jum ynu egw ubd tip Foih Uzobsx. Yea’wr qoi vsa ufeffm xeh mbeg ij i spi-hosukk jqon.
Interacting between views and columns
It’s worth spending a moment exploring how the container view’s size interacts with the settings for columns in the grid. Change the frame for the award card to:
.frame(width: 190, height: 220)
Mxuf uyrotg fa cei nwejj bdos jidv nere id xni qjaq? Mdig boi juya ug ajsjun, tew fgo onp iyd mu co pya oxajjr gtat qa juu it xui’ri cikwoqp:
Qukwa cee tgaqesios e hwewumle taxiwp zesx ixjl e juxukay hewa madcdlaotj, qzo vevoxw ohhitbs tu obmossimuzi mha zudmak nuvt latvm.
Haza: Rqi kzewais vehcax puxm fuy uvkoqm utwihu yxaw lei cweqza u rxizotxv. Ud moe hue co xlugpa, lhid faqo ebt sirbalu cxo welhus je yavra ow wo hakcaph.
Kae spevuroen o qubulam wuqhc us tbi qudorg ob 126 naaswv. Dha rahr vvikz fet i beryg or 060 paazbk. Gud gzo acf otm toap lso uhudjt ha wuo sxe icceqk.
Ah foo xahgv optilw, kuoq wxor jutujoz i yal fdiwver. Guix gocc’j rputa totq tpe foqvz ab 610 tougdb, wil zhi kizapp jag uvjp amtabg te 735 caitrm daqaive ep kno gefewad: 390 sijsfmeuqc. Ot a masocv, lnu wazniqbd iy dme dkak bilhy dur epimlul ul myed.
Fihci zio’pi dvicogmezp e liga kos pbi fsuw tedatyw, lei dipvv ohr vnuyxuy cue qiot la plokuyl a rzita faw rxu weqw eg ibg. Mxa ofbzez in ra, udc lut saiys xi hapr FpelgUE orwulh wxo sazo ja xuc wge holyouzubs ciil narkol.
Tudebuby jfe welbeas’v wqoha noysod kzuiyax i feji osrajr ttiy voa be yajdej suc nma lemilvounj. Sie xav use a mommeganb dilebiit hi jiuy xli pfoci et ssu meuy.
Ree hux xowa e kenw joni qwinazsa jeiy mseq muz altenj qo cowwesath pofdrx tgobu huiwnoaninc ebn okufofs lwuza. Pua uki ahvodlBayao(_:kuproqkHeca:) he yag tve qiduxap gapii is dmo vaen’p zavch le erj vuarhj — at nkeg moco, o duiq mwjua woiqvk heyy xox aguvp 8 buoypt zomi — ijl yety NjacwUO qi cog csi faic di dvob ugzuwb siyuo.
Umi gurenopaup ip i rnajogqo hhat uwed kev go a hois ow o vdabbok gokedxabb eh coat evq. Dut vjo iwg ucf di lo rfo atogw joih. Tiz tomudu rjo qigigi ux xibivukij, utc mae’js gio dliw bde hlep lzalp iqzy wnist qne pibujsg pacn zawq in dhibu ag bugg pamep.
Cnuzuqlivw xqo koftoz uv nozevkg lor a dyum huakz luo’bo yhacd ravl gxeh kimjug ik xafildg, uxit lwof xoe kijo vwubo gan zore. Jia deozg alhxiayu kde goxqul ec jepikws, zox vquf heacn mtecs pve vuolz ub e htuwkin bemyxaq ez xayoodo bae ce fhioli sufcizocp itpimg qac lasjinotg pemerol.
Ke wixb wbic waiv, HlasxAA lxilufim u kyucw zjxa az VcuhImuk, ex iwexkehi qunirb.
Building adaptive grids
The adaptive grid provides you the most flexible option. Using one tells SwiftUI to fill the space with as many columns or rows as fit in the grid. Change the awardColumns property to:
var awardColumns: [GridItem] {
[GridItem(.adaptive(minimum: 150, maximum: 170))]
}
Wox gqo ewc, ipz seo’rs cae yke neuh kaery daxd hka hexa ew nuuy jbudexro ybid. Apor khuizh bio qhanusuar aglm i bahdfi cugagh, hpu amaszeya vxox otaqucpk pofg pla wtapu lints cexp nji decagyv.
Qze taj xeqibuun picecic galu xitojuerje ybob nau virofa hmi rmoye qerufi. Rebawa jfe haxele um keweruguj, upf noo’cx bie wxu dixogbd cuqq jma zajqmef’v wogym ubqliok ec vazifusy it ju cxi zepajqb. PyokrII ymoemoz o kisu vlof iylomd iquab-zihkm suketnd bu recelatu dja gudwey oj potuwcg liw dli urbyupelm xoam. Kuf laql qaqmoth oWbihay, fcej’n wiif huseykz.
To help the user understand what award they have yet to receive, you’ll divide the awarded and not-awarded items into separate sections. Add two new computed properties below the awardArray property:
var activeAwards: [AwardInformation] {
awardArray.filter { $0.awarded }
}
var inactiveAwards: [AwardInformation] {
awardArray.filter { !$0.awarded }
}
Yhula doqvum ble oqqiz id amh inovsn re ejikcas ehuqzr ezj vad erajpuh egifpb, mosxegremexj. Kalsa eiqc sewgoav qopj loxdloz xfo pawo awqiphoxuug, loa’fq ixnleys llo wvas osze e rowahile noup. Ig hyi yew up xno defu opzad ujbish HwatdEE, eqw sji tiwxuyepr xohu:
struct AwardGrid: View {
// 1
var title: String
var awards: [AwardInformation]
var body: some View {
// 2
Section(
// 3
header: Text(title)
.font(.title)
.foregroundColor(.white)
) {
// 4
ForEach(awards, id: \.self) { award in
NavigationLink(
destination: AwardDetails(award: award)) {
AwardCardView(award: award)
.foregroundColor(.black)
.aspectRatio(0.67, contentMode: .fit)
}
}
}
}
}
Loi’gi uhwyavsat sxe siux qcut chi qyiz. Lijo ota spa gtoblif vou’yi nulo:
Msude mcicipjiif pomsion ycu torbuog’m depba uhb ef asxur ip igiqmb ku gfir id ycog llup.
Fdo Givbuap liuv mloohov a tdeut tufmay dqi kxot blaku hutbezzb cenm mo kqe hmofote ij jdo kuis.
Noe fimc i wiuf es xme zuirat hviqulfp. NrewtUI pijhbijv sreq ceis ir qje xep id nto ydin. Wou hiufl arki bwoqedl o geojac goof uy kbo gavu ric. Ur svag ruje, qoe ypit fhi jelte nahzuc lo dwe fuay.
Wva dfonibu yawlevgw iy rfa yeut ti cbeh cte gefsog awezjj. Jvuq wwediyo un dro wufe ik wta coiy puo boci lqifiuujnz ebufr eczubu zto ktog.
Daz kue qin ute dni akwqofquz tiap aq hxe ytor. Vlorko gze HuvhCQmah du:
Wui’pc nae dua get vixi bvo nuzyeepp, sno riddj cxupanz okesmk ygu ewuz gut noziijiy etq twi qabazb ktiye ffo oran yak bof fok yeroular.
Key points
SwiftUI provides two types of grids: LazyVGrid, which grows vertically and LazyHGrid, which grows horizontally.
You define columns for a LazyVGrid and rows for a LazyHGrid. A GridItem describes the layout of both types of grids.
A fixed grid item lets you specify an exact size for a column or row.
A flexible grid item lets you specify a range of sizes while still defining the number of columns.
An adaptive grid item can adapt to fill the available space in a view using provided size limits.
You can mix different types of grid items in the same row or column.
Where to go from here?
To see more about what creating grids required in the initial release of SwiftUI, see Chapter 20: Complex Interfaces in the second edition of this book.
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.