Table of Contents
Inleiding tot Dynamische Collectie Weergaven in SwiftUI
Moderne iOS-apps vereisen vloeistof, adaptieve interfaces die sierlijk reageren op verschillende dataformaten, apparaatoriëntaties en schermafmetingen. In UIKit bieden collectieweergaven een krachtig maar werkwoordelijk mechanisme voor het bouwen van rasterachtige lay-outs. SwiftUI vereenvoudigt dit dramatisch met zijn declaratieve API, vooral door LazyVGrid en LazyHGrid[]. Deze componenten laten ontwikkelaars dynamische, resizeable roosters met minimale code definiëren, waardoor het gemakkelijker wordt om productie-ready UIs te bouwen die werken over iPhones, iPads en zelfs Mac Catalyst targets.
Een dynamische collectie weergave lay-out past zijn kolomtelling, rijhoogte, afstand, of grootte gedrag op basis van de beschikbare containerbreedte, het aantal items, of de inhoud zelf. Dit artikel zal u begeleiden door het bouwen van dergelijke lay-outs in SwiftUI, die alles bestrijken van basisraster setup tot geavanceerde adaptieve gedrag, prestaties tuning, en integratie met animaties. Tegen het einde, zult u een solide basis voor het creëren van flexibele, aantrekkelijke en performante collectie weergaven in uw eigen apps.
Kerncomponenten: LazyVGrid en LazyHGrid
SwiftUI levert twee primaire roostercontainers: LazyVGrid (verticale scrolling grid) en LazyHGrid[] (horizontaal scrolling grid). Beide lui laden hun kinderen, wat betekent dat de weergaven alleen worden gemaakt als ze zichtbaar worden op het scherm .Een cruciale eigenschap voor het hanteren van grote datasets zonder geheugen opgeblazen. Deze containers zijn analoog aan in UIKit, minus de ketelplaat van databron en gedelegeerde protocollen.
RasterItemconfiguratie
Om een rasterstructuur te definiëren, maakt u een array van GridItem instanties. Elke vertegenwoordigt een enkele kolom (in ) of een enkele rij (in ). U bepaalt drie sleuteleigenschappen:
- Size
- Spacing .. Horizontale afstand tussen items in dezelfde rij (voor verticale roosters) of verticale afstand (voor horizontale roosters).
- Uitlijning
De keuze van de groottemodus bepaalt de algemene lay-out flexibiliteit:
- Fixed
- Flexibel
- Adaptive
Om bijvoorbeeld een raster te maken dat automatisch zoveel mogelijk kolommen past, elk met een minimale breedte van 100 punten, zou je schrijven:
let columns = [
GridItem(.adaptive(minimum: 100))
]
Deze enkele lijn levert een lay-out die zich aanpast van een kolom op een smalle iPhone naar verschillende kolommen op een iPad in het landschap . . precies het gedrag dat we willen voor dynamische lay-outs.
Bouwen van een basis dynamisch raster
Laten we beginnen met een eenvoudig, volledig dynamisch raster met behulp van sizing. Hieronder is een compleet uitzicht dat een reeks van snaren in een responsief raster toont:
struct AdaptiveGridView: View {
let items = Array(1...20).map { "Item \($0)" }
var body: some View {
ScrollView {
LazyVGrid(
columns: [GridItem(.adaptive(minimum: 80), spacing: 12)],
spacing: 12
) {
ForEach(items, id: \.self) { item in
Text(item)
.frame(minWidth: 80, maxWidth: .infinity, minHeight: 80)
.background(Color.blue.opacity(0.2))
.cornerRadius(8)
}
}
.padding()
}
}
}
Hier wordt elk item gedwongen tot ten minste 80 punten breed en hoog. Het raster item berekent dan automatisch hoeveel items passen per rij gezien de beschikbare breedte, met inachtneming van de minimale breedte. Het resultaat is een lay-out die naadloos herstroomt wanneer het apparaat draait of het venster wordt aangepast (op iPad of Mac).
Deze aanpak werkt goed voor eenvoudige inhoud, maar voor meer controle moet je vaak combineren met items, of gebruiken om aangepaste kolom telt.
Met behulp van GeometrieReader voor nauwkeurige dynamische kolomtellingen
Terwijl veel gevallen behandelt, soms wilt u een exact aantal kolommen instellen op basis van de containerbreedte . Bijvoorbeeld, altijd 2 kolommen op een iPhone in portret, 3 in landschap, en 4 op iPad. De GeometrieReader] weergave geeft de huidige grootte van de ouder, zodat u de optimale kolom dynamisch kunt tellen.
Voorbeeld: Een adaptieve kolomtelling
De volgende weergave leest de beschikbare breedte en berekent een kolomtelling op basis van een doelitembreedte:
struct DynamicColumnGridView: View {
let items = Array(1...30).map { "Item \($0)" }
let targetItemWidth: CGFloat = 120
var columns: [GridItem] {
let count = max(Int(geometryProxy.size.width / targetItemWidth), 1)
return Array(repeating: GridItem(.flexible(), spacing: 12), count: count)
}
var body: some View {
GeometryReader { geometry in
ScrollView {
let width = geometry.size.width
let count = max(Int(width / targetItemWidth), 1)
let columns = Array(repeating: GridItem(.flexible(), spacing: 12), count: count)
LazyVGrid(columns: columns, spacing: 12) {
ForEach(items, id: \.self) { item in
Text(item)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 80)
.background(Color.green.opacity(0.3))
.cornerRadius(8)
}
}
.padding()
}
}
}
}
Belangrijk: In de praktijk moet je de waarde in een variabele opslaan of gebruiken binnen dezelfde sluiting. In het bovenstaande voorbeeld wordt een hulpvariabele gebruikt binnen de sluiting voor duidelijkheid. Zorg er altijd voor dat je het gehele lichaam niet in inpakt zonder dat dit de lay-out kan breken indien gebruikt als de bovenste weergave.
Deze techniek geeft u volledige controle over het aantal kolommen, terwijl het houden van items flexibel, zodat ze de breedte gelijkmatig vullen. U kunt ook minimale en maximale beperkingen toevoegen aan de flexibele items om extreem uitgestrekte of geplooide cellen te voorkomen.
Rijhoogtes dynamisch aanpassen
Dynamische lay-outs zijn niet alleen over kolommen . . rij hoogtes kunnen ook variëren op basis van de inhoud. SwiftUI doet niet een directe . .Autumn Sizing ..raster zoals UIKit .. met geschatte groottes. Echter, u kunt vergelijkbare resultaten bereiken met behulp van intrinsieke inhoud grootte en of door het inbedden van data-gedreven hoogtes.
Bijvoorbeeld, kunt u elke raster cel zelf-grootte maken door expliciete hoogtes weg te laten en de interne inhoud de grootte te laten bepalen. SwiftUI berekent automatisch de celhoogte op basis van het hoogste item in elke rij (voor verticale rasters). Maar als u echt variabele rijhoogtes nodig hebt (zoals een metselwerk lay-out), moet u een aangepaste aanpak .. vaak met behulp van met aangepaste uitlijningshandleidingen of het inpakken van het raster in een ] maar met verschillende hoogtes per kolom. Dat is meer geavanceerde en buiten het bereik van dit artikel, maar de sleutelafhaal is dat alle cellen in een rij dezelfde hoogte (bepaald door de hoogste cel) delen. Als uw ontwerp vereist variabele hoogtes, overwegen met behulp van een met een aangepaste raster lay-out.
Lazy Lading van grote gegevenssets
Een van de belangrijkste voordelen van .2]] en .2]] is hun luie laadgedrag. Ze creëren alleen views voor de items die momenteel zichtbaar zijn (plus een kleine buffer). Dit maakt ze efficiënt voor datasets met honderden of zelfs duizenden items. Er zijn echter een paar beste praktijken om de prestaties soepel te houden:
- Gebruik stabiele identificaties
- Vermijd dure berekeningen in het lichaam .Blijf celweergaven eenvoudig. Als u complexe lay-outberekeningen nodig hebt, precomputeer ze dan buiten het raster.
- Hefboom
- Gebruik in een . Indien u een nestelt in een andere luie container, kunt u lui laden breken. Typisch, het raster zelf moet het directe kind van een zijn (of in een container worden verpakt).
Dynamische lay-outs combineren met animaties
Animaties in SwiftUI kunnen lay-outwijzigingen natuurlijk en gepolijst laten voelen. Bijvoorbeeld, wanneer het aantal kolommen verandert (door rotatie of venstergrootte), kunt u de rasteritems animeren naar hun nieuwe posities. De gemakkelijkste manier is om het raster in een te wrapen of de te gebruiken met een waarde die verandering inschakelt.
Kolomwijzigingen animeren
Hier een uitbreiding van het eerdere dynamische kolom voorbeeld met een geanimeerde overgang:
struct AnimatedDynamicGridView: View {
let items = Array(1...20).map { "Item \($0)" }
@State private var targetItemWidth: CGFloat = 120
var body: some View {
GeometryReader { geometry in
ScrollView {
let width = geometry.size.width
let count = max(Int(width / targetItemWidth), 1)
let columns = Array(repeating: GridItem(.flexible(), spacing: 12), count: count)
LazyVGrid(columns: columns, spacing: 12) {
ForEach(items, id: \.self) { item in
Text(item)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 80)
.background(Color.orange.opacity(0.4))
.cornerRadius(8)
.transition(.scale.combined(with: .opacity))
}
}
.padding()
.animation(.spring(response: 0.4, dampingFraction: 0.7), value: count)
}
}
}
}
Door de animatie aan de waarde te koppelen, zal SwiftUI de invoeging, verwijdering en herschikking van items animeren wanneer het aantal kolommen verandert. U kunt ook gebruiken voor meer geavanceerde overgangen tussen lay-outs.
Praktische voorbeelden: Dynamische lay-outs van Real-World
Laat ons door twee gemeenschappelijke scenario's lopen die profiteren van dynamische collectie weergave lay-outs.
Fotogalerijraster
Een typische fotogalerij gebruikt een vierkant celraster dat zich aanpast aan de schermbreedte. U wilt dat de cellen zo groot mogelijk zijn terwijl u een vast aantal kolommen (bijv. 2 op iPhone, 3 op iPhone Plus, 4 op iPad) behoudt. Het gebruik van met een voorwaardelijke kolom tellen op basis van grootteklassen is eenvoudig:
struct PhotoGalleryGrid: View {
let images: [String]
@Environment(\.horizontalSizeClass) var sizeClass
var columns: [GridItem] {
let count = sizeClass == .compact ? 2 : 4
return Array(repeating: GridItem(.flexible(), spacing: 2), count: count)
}
var body: some View {
ScrollView {
LazyVGrid(columns: columns, spacing: 2) {
ForEach(images, id: \.self) { imageName in
Image(imageName)
.resizable()
.aspectRatio(1, contentMode: .fill)
.clipped()
}
}
.padding(.horizontal, 2)
}
}
}
Dynamisch Dashboard met variabele celgroottes
Voor een dashboard, zou je cellen van verschillende breedtes .. bijvoorbeeld, een grote grafiek nemen van twee kolommen, kleinere statistieken nemen van een kolom elk. U kunt dit bereiken door het combineren van items met expliciete multiplicatoren met behulp van een aangepaste array. Bijvoorbeeld:
let columns: [GridItem] = [
GridItem(.flexible(minimum: 80), spacing: 12), // small stat cell
GridItem(.flexible(minimum: 160), spacing: 12), // wide cell
GridItem(.flexible(minimum: 80), spacing: 12) // small stat cell
]
Vervolgens kunt u in het rooster verschillende gegevenstypen in kaart brengen naar verschillende kolombereiken door items in een container te verpakken die uitbreidt om de rasterbreedte te vullen. Dit vereist een zorgvuldige coördinatie omdat de multikolomspanwijdte niet in eigen beheer ondersteunt. Een gemeenschappelijke aanpak is te gebruiken -modifier (beschikbaar in iOS 16+) of handmatig indexeer het raster door uw gegevens op te splitsen in secties die elk een volledige rij vullen.
Voor iOS 16 en later kunt u de modifier gebruiken op een weergave in het raster om aan te geven hoeveel kolommen die weergave moet overspannen:
LazyVGrid(columns: columns, spacing: 12) {
ForEach(dashboardItems, id: \.id) { item in
DashboardCell(item: item)
.gridCellColumns(item.columnSpan)
}
}
Dit is de schoonste manier om een echte dynamische dashboard lay-out met gemengde celgroottes te creëren.
Prestatieoverwegingen voor grote gegevenssets
Bij het omgaan met duizenden items, zelfs luie belasting kan leiden tot vertragingen als elke cel complex is. Hier zijn geavanceerde technieken om uw dynamische rasters glad te houden:
- Voer afbeeldingen en gegevens voor
- Gebruik voor extreem grote lijsten[ . . SwiftUI
- Recomputatie van layout beperken
- Gebruik op het gehele raster Als je de rasterstructuur volledig verandert (bijvoorbeeld overstappen van 2 kolommen naar 3), dan heeft het toewijzen van een nieuwe ] aan het raster het geheel gedwongen om te herladen, wat sneller kan zijn dan het proberen om een complexe verandering te animeren.
Externe bronnen om je kennis te verdiepen
Om dynamische collectie-views in SwiftUI verder te verkennen, verwijzen we naar deze officiële en communautaire bronnen:
- Apple
- Snelstartgids voor GridItem .Boekt alle drie de groottestrategieën met interactieve voorbeelden. Aanvragen Ontwikkelaar Documentatie: GridItem
- SwiftUI by Example
- SwiftUI Lab: Lazy Grids . . . Diep duiken in prestaties en aanpassingen. SwiftUI Lab: Lazy Grids
Samenvatting van beste praktijken
Het creëren van een dynamische collectie weergave lay-out in SwiftUI vereist evenwicht flexibiliteit met prestaties. Hier een snelle checklist voor productie-klaar grids:
- Begin met voor de eenvoudigste dynamische kolomtelling; gebruik alleen wanneer u nauwkeurige controle nodig heeft.
- Geef altijd unieke waarden of conform .
- Gebruik met een waarde die verandert (zoals kolomtelling) om overgangen te vergemakkelijken.
- Voor gemengde celgroottes, verkies op iOS 16+ of ontwerp een aangepaste rij-op-rij lay-out.
- Profiel uw raster met Instrumenten om te controleren of lui laden werkt en cellen zijn niet renderen offscreen inhoud.
- Test op meerdere apparaatgroottes en oriëntaties . . dynamische lay-outs die er geweldig uitzien op het ene scherm kan breken op een ander.
Het beheersen van dynamische collectie weergaven stelt u in staat om apps te bouwen die zich native en responsief voelen op elk Apple-apparaat. Met SwiftUI... kunt u bereiken wat ooit tientallen regels van UIKit-code nodig had in slechts een handvol expressieve, herbruikbare componenten.