Reputation: 180
I'm using a 4-block grid for my Widget Extension.
I want to populate these grids with an array of elements.
let exampleArray = ["test1","test2","test3","test4"]
When I use two nested ForEach loops, I can't get the element in the 4th index.
VStack {
ForEach((0..<2)) { column in
HStack {
ForEach((0..<2)) { index in
ZStack (alignment: .bottomLeading) {
Text(newsList[(index+column)]) // 0+0, 1+0, 0+1, 1+1
// Text = test1, test2, test2, test3
}
}
}
}
}
Any way I can work around this? Because it's in View
, I can't use any operations.
Full code of the View:
struct AppWidgetEntryView : View {
var entry: Provider.Entry
@Environment(\.widgetFamily)
var widgetFamily
var body: some View {
VStack(alignment: .trailing, spacing: 6) {
Image("logo")
.frame(maxWidth: .infinity, alignment: .leading)
if widgetFamily == .systemLarge {
VStack {
ForEach((0..<2)) { column in
HStack {
ForEach((0..<2)) { index in
ZStack (alignment: .bottomLeading) {
if let url = URL(string: imageList[(index+column)]), let imageData = try? Data(contentsOf: url),
let uiImage = UIImage(data: imageData) {
Image(uiImage: uiImage)
.centerCropped()
.frame(maxHeight: 150, alignment: .center)
.cornerRadius(10)
.overlay(RoundedRectangle(cornerRadius: 10)
.stroke(Color.gray, lineWidth: 1))
.shadow(radius: 10)
} else {
Image("ph_background")
.centerCropped()
.frame(maxHeight: 150, alignment: .center)
.cornerRadius(10)
.overlay(RoundedRectangle(cornerRadius: 10)
.stroke(Color.gray, lineWidth: 1))
.shadow(radius: 10)
}
Text(newsList[(index+column)])
.font(.system(size: 12))
.foregroundColor(.white)
.fontWeight(.light)
// .frame(maxHeight: 50)
.background(Rectangle().fill(Color.black).blur(radius: 20))
.padding(.bottom, 5)
.padding(.leading, 5)
.padding(.trailing, 5)
.padding(.top, 5)
}
}
}
}
}
}
}
}
Solution Please check the accepted answer.
struct AppWidgetEntryView : View {
var entry: Provider.Entry
@Environment(\.widgetFamily)
var widgetFamily
var body: some View {
var columns: [GridItem] =
Array(repeating: .init(.fixed(100)), count: 2)
if widgetFamily == .systemLarge {
LazyVGrid(columns: columns) {
ForEach((0..<4)) { index in
ZStack (alignment: .bottomLeading) {
if let url = URL(string: imageList[(index)]), let imageData = try? Data(contentsOf: url),
let uiImage = UIImage(data: imageData) {
Image(uiImage: uiImage)
.centerCropped()
.frame(maxHeight: 150, alignment: .center)
.cornerRadius(10)
.overlay(RoundedRectangle(cornerRadius: 10)
.stroke(Color.gray, lineWidth: 1))
.shadow(radius: 10)
} else {
Image("ph_background")
.centerCropped()
.frame(maxHeight: 150, alignment: .center)
.cornerRadius(10)
.overlay(RoundedRectangle(cornerRadius: 10)
.stroke(Color.gray, lineWidth: 1))
.shadow(radius: 10)
}
Text(newsList[(index)])
.font(.system(size: 12))
.foregroundColor(.white)
.fontWeight(.light)
// .frame(maxHeight: 50)
.background(Rectangle().fill(Color.black).blur(radius: 20))
.padding(.bottom, 5)
.padding(.leading, 5)
.padding(.trailing, 5)
.padding(.top, 5)
}
}
}
}
}
}
Upvotes: 0
Views: 314
Reputation: 77641
LazyVGrid
I feel like you really should be using LazyVGrid
for this...
https://developer.apple.com/documentation/swiftui/lazyvgrid
It works like a List
but it places each item in a grid of columns.
Using this will solve this problem for you.
LazyVGrid
If you really don't want to use a LazyVGrid
(please use this though). Then the calculation you are using is not correct. The calculation is something like...
index = row*numberOfCols + column
You can't just use the row as that will only increase the index by 1 per row. But you need to increase the index by the number of columns per row (2 in your case).
Upvotes: 2