我想要一个可变长度的数组,并返回具有3列和可变行长的视图网格。该视图应根据数组值更新其内容。
以下代码将为每张卡显示一个CardPicView,在滚动视图中标题为“ A” ...“ I”。
struct ContentView : View {
let cards = ["A", "B", "C", "D", "E", "F", "G", "H", "I"]
var body: some View {
ScrollView {
ForEach(cards.identified(by: \.self)) { card in
CardPicView(cardTitle: card)
}
}
}
}
我想使用此滚动视图,基本上将其分为3列。
我发现以下代码可以使用以下方法创建正确大小的网格:
struct ContentView : View {
let cards = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]
var body: some View {
ScrollView{
ForEach(0..<cards.count/3) { row in // create number of rows
HStack {
ForEach(0..<3) { column in // create 3 columns
Text(self.cards[row])
}
}
}
}
}
}
但是,这给了我一个只有(AAA / BBB / CCC / DDD)的3x4网格
更改为:
struct ContentView : View {
let cards = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]
var body: some View {
ScrollView{
ForEach(0..<cards.count/3) { row in // create number of rows
HStack {
ForEach(0..<3) { column in // create 3 columns
Text(self.cards[column])
}
}
}
}
}
}
给我一个只有(ABC / ABC / ABC / ABC)的3x4网格。
我不知何故需要使用两个索引在行和列上进行迭代,但不确定如何迅速进行。
答案 0 :(得分:1)
我认为SwiftUI并没有阻止它的特定功能。我认为这就是您要完成的工作?
struct ContentView : View {
let cards = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]
var body: some View {
ScrollView{
ForEach(0..<cards.count/3) { row in // create number of rows
HStack {
ForEach(0..<3) { column in // create 3 columns
Text(self.cards[row * 3 + column])
}
}
}
}
}
}
答案 1 :(得分:0)
这是我使用Swift泛型的方法。
import SwiftUI
struct Grid<Content: View>: View {
let rows: Int
let columns: Int
let content: (Int, Int) -> Content
var body: some View {
VStack(alignment: .leading, spacing: 10) {
ForEach(0..<rows) { row in
Divider()
HStack(alignment: .center, spacing: 30) {
ForEach(0..<self.columns) { (column) in
self.content(row, column)
.padding()
}
.background(LinearGradient(gradient: Gradient(colors: [Color.yellow, Color.green]), startPoint: .leading, endPoint: .trailing))
.clipShape(Capsule())
.shadow(radius: 3)
}
}
Divider()
}
}
}
struct CardPicView: View {
@State var displayText: String
var body: some View {
HStack(alignment: .center, spacing: 4) {
Image(systemName: "\(displayText).circle.fill")
.foregroundColor(.blue)
Text(displayText)
.multilineTextAlignment(.leading)
.frame(maxWidth: .infinity)
Spacer(minLength: 0)
}
.font(.title) // sets equal hight both for image and text
.frame(maxWidth: .infinity)
}
}
struct ContentView: View {
var cards = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "w", "l", "m", "n", "ww"]
@Environment(\.horizontalSizeClass) var horizontalSizeClass
private var numberOfcolumns: Int {
(horizontalSizeClass == .compact) ? 2 : 4
}
// need to ensure number of rows is rounded up to the next whole integer
private var numberOfrows: Int {
Int(ceil(Double(cards.count)/Double(numberOfcolumns)))
}
var body: some View {
ScrollView {
Grid(rows: numberOfrows, columns: numberOfcolumns) { (r, c) in
CardPicView(displayText: self.cards[guarded: r*self.numberOfcolumns + c] ?? "_")
}
.padding()
}
.background(Color(red: 1.0, green: 0.6, blue: 0.95))
}
}
// subscript for safe access
extension Array {
subscript(guarded idx: Int) -> Element? {
guard (startIndex..<endIndex).contains(idx) else { return nil }
return self[idx]
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
Group {
ContentView()
.environment((\.horizontalSizeClass), .compact)
ContentView()
.previewDevice(PreviewDevice(stringLiteral: "iPad8,5"))
.environment((\.horizontalSizeClass), .regular)
}
}
}
答案 2 :(得分:-2)
基于ZStack的示例here
您可以选择固定列样式。
Grid(self.cards) { card in
Card(title: "\(number)")
}
.gridStyle(
FixedColumnsGridStyle(columns: 3, itemHeight: 160)
)