Reputation: 1654
Is SwiftUI 2 grid system is able to render "Masonry like" layouts ?
A "Masonry" layout will look like this :
The remarkable feature of this layout is that content can span on multiple columns.
This does not seems automatically possible with LazyVGrid or LazyHGrid as they rely on GridItem which seems to describe a column (either fixed, flexible or adaptive).
If you think in term of column this design cannot be achieved.
Did i missed something or is it true we cannot make this kind of grid ?
Upvotes: 2
Views: 2100
Reputation: 3446
I must admit that I haven't done much research for Lazy Grids yet, but as I saw some examples, I'm afraid that it will not be possible that way. But my programming mindset is: anything is possible. So let's make our own solution! Here's mine:
struct ContentView: View {
let items = (1 ... 12).map { "Item \($0)" }
var range: Range<Int> { 0 ..< Int((Double(items.count) / 3).rounded(.up)) }
var body: some View {
GeometryReader { geometry in
ScrollView {
LazyVStack { // still some laziness
ForEach(range, id: \.self) { index in
HStack(spacing: 0) {
if index % 2 == 0 {
Text(items[index * 3])
.frame(maxHeight: .infinity)
.frame(width: geometry.size.width * 2/3)
.background(Color(#colorLiteral(red: 0.3427395821, green: 0.7238617539, blue: 0.6179549098, alpha: 1)))
VStack(spacing: 0) {
Text(items[index * 3 + 1])
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(#colorLiteral(red: 0.1351453364, green: 0.1446713805, blue: 0.2671209574, alpha: 1)))
Text(items[index * 3 + 2])
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(#colorLiteral(red: 0.9248386621, green: 0.3957888484, blue: 0.3508865833, alpha: 1)))
}
.frame(maxHeight: .infinity)
.frame(width: geometry.size.width * 1/3)
} else {
VStack(spacing: 0) {
Text(items[index * 3])
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(#colorLiteral(red: 0.1351453364, green: 0.1446713805, blue: 0.2671209574, alpha: 1)))
Text(items[index * 3 + 1])
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(#colorLiteral(red: 0.9248386621, green: 0.3957888484, blue: 0.3508865833, alpha: 1)))
}
.frame(maxHeight: .infinity)
.frame(width: geometry.size.width * 1/3)
Text(items[index * 3 + 2])
.frame(maxHeight: .infinity)
.frame(width: geometry.size.width * 2/3)
.background(Color(#colorLiteral(red: 0.226172477, green: 0.3690122366, blue: 0.3273729682, alpha: 1)))
}
}
.frame(height: geometry.size.width * 6/16)
}
}
}
}
.foregroundColor(.white)
}
}
Explanation:
let items = ...
is just a quick way to generate a list with strings "Item 1" through "Item 12".range
will contain the number of rows..frame(maxHeight: .infinity)
to make the items fill the available space.index * 3
, index * 3 + 1
and index * 3 + 2
, where index
is the row number. I will illustrate that with the table below:
+-------------------------------------------+-------------------------------------------+-------------------------------------------+-------------------------------------------+
| index = 0 | index = 1 | index = 2 | index = 3 |
+-----------+---------------+---------------+-----------+---------------+---------------+-----------+---------------+---------------+-----------+---------------+---------------+
| index * 3 | index * 3 + 1 | index * 3 + 2 | index * 3 | index * 3 + 1 | index * 3 + 2 | index * 3 | index * 3 + 1 | index * 3 + 2 | index * 3 | index * 3 + 1 | index * 3 + 2 |
| = 0 | = 1 | = 2 | = 3 | = 4 | = 5 | = 6 | = 7 | = 8 | = 9 | = 10 | = 11 |
+-----------+---------------+---------------+-----------+---------------+---------------+-----------+---------------+---------------+-----------+---------------+---------------+
Upvotes: 1