苹果介绍了在SwiftUI中制作CollectionViews的方法,通过使用新的LazyVGrid和嵌入ScrollView中的LazyHGrid。
但是,如果最后一行的元素少于列数,则这些项显示为与leading对齐。可以将最后一行项目与.center对齐
Swift 5.3 - SwiftUI 2.0 - Xcode 12.0b - macOS 11大压力
发布于 2020-06-30 17:17:02
我不知道这在LazyGrid中是否可行,但这里有一个可能的解决方法:
只要数据数组中的项数量不均匀,就可以简单地将最后一项放在VStack中并将其居中对齐。
我已经为您实现了一个演示:

简单:
import SwiftUI
//MARK: - Content
struct ContentView: View {
//Your data
let data = Array(0...4)
let columns = [
GridItem(.fixed(160)),
GridItem(.fixed(160))
]
//Same spacing both for items inside grid and between grid and stack
let rowSpacing: CGFloat = 32
//If number of items is odd, remove the last one from grid and add to stack
var gridData: [Int] { data.count%2 == 1 ? data.dropLast() : data }
var stackData: Int? { data.count%2 == 1 ? data.last : nil }
var body: some View {
ScrollView {
VStack(spacing: rowSpacing) {
LazyVGrid(columns: columns, spacing: rowSpacing) {
ForEach(gridData, id: \.self) { i in
ItemView(i: i)
}
}
if let data = stackData {
VStack {
ItemView(i: data)
}
}
}
}
}
}
//MARK: - Item
struct ItemView: View {
let i: Int
var body: some View {
Rectangle()
.frame(width: 160, height: 240)
.foregroundColor(Color.green)
.overlay(Text(String(i)).foregroundColor(.white))
}
}可选的,可重用的:
//MARK: - Data
struct SampleData: Identifiable {
let id: Int
var text: String
}
//MARK: - View
struct ContentView: View {
//Your data
let data = [SampleData(id: 0, text: "A"), SampleData(id: 1, text: "B"), SampleData(id: 2, text: "C")]
let columns = [
GridItem(.fixed(160)),
GridItem(.fixed(160))
]
var body: some View {
ScrollView {
CenteredLazyVGrid(data, columns: columns, spacing: 32) { i in
ItemView(i: i.id)
}
}
}
}
//MARK: - Item
struct ItemView: View {
let i: Int
var body: some View {
Rectangle()
.frame(width: 160, height: 240)
.foregroundColor(Color.green)
.overlay(Text(String(i)).foregroundColor(.white))
}
}
//MARK: - Centered Grid View
struct CenteredLazyVGrid<Data, Content>: View where Data: RandomAccessCollection, Content: View, /*Data: Hashable, */Data.Element: Identifiable {
private var data: Data
//private var id: KeyPath<Data.Element, ID>
private var columns: [GridItem]
private var alignment: HorizontalAlignment = .center
private var spacing: CGFloat? = nil
private var pinnedViews: PinnedScrollableViews = []
private var content: (Data.Element) -> Content
init(_ data: Data, /*id: KeyPath<Data.Element, ID>, */columns: [GridItem], alignment: HorizontalAlignment = .center, spacing: CGFloat?
= nil, pinnedViews: PinnedScrollableViews = .init(), content: @escaping (Data.Element) -> Content) {
self.data = data
//self.id = id
self.columns = columns
self.alignment = alignment
self.spacing = spacing
self.pinnedViews = pinnedViews
self.content = content
}
private var gridData: [Data.Element] { data.count%2 == 1 ? data.dropLast() : data as! [Data.Element] }
private var stackData: Data.Element? { data.count%2 == 1 ? data.last : nil }
var body: some View {
VStack(spacing: spacing) {
LazyVGrid(columns: columns, alignment: alignment, spacing: spacing, pinnedViews: pinnedViews) {
ForEach(gridData/*, id: id*/) { i in
content(i)
}
}
if let data = stackData {
VStack {
content(data)
}
}
}
}
}https://stackoverflow.com/questions/62652655
复制相似问题