45 lines
1.9 KiB
Swift
45 lines
1.9 KiB
Swift
import SwiftUI
|
|
|
|
/// All card positions are calculated in the same transaction as the bookmark flight.
|
|
struct LeadCardGrid: Layout {
|
|
let columnCount: Int
|
|
var spacing: CGFloat = 16
|
|
|
|
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
|
|
let width = proposal.width ?? 310
|
|
let frames = frames(width: width, subviews: subviews)
|
|
return CGSize(width: width, height: frames.map(\.maxY).max() ?? 0)
|
|
}
|
|
|
|
func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize,
|
|
subviews: Subviews, cache: inout ()) {
|
|
let frames = frames(width: bounds.width, subviews: subviews)
|
|
for (index, subview) in subviews.enumerated() {
|
|
let frame = frames[index]
|
|
subview.place(at: CGPoint(x: bounds.minX + frame.minX, y: bounds.minY + frame.minY),
|
|
anchor: .topLeading,
|
|
proposal: ProposedViewSize(width: frame.width, height: frame.height))
|
|
}
|
|
}
|
|
|
|
private func frames(width: CGFloat, subviews: Subviews) -> [CGRect] {
|
|
let columns = max(1, columnCount)
|
|
let cardWidth = max(0, (width - CGFloat(columns - 1) * spacing) / CGFloat(columns))
|
|
var frames: [CGRect] = []
|
|
var rowY: CGFloat = 0
|
|
var rowHeight: CGFloat = 0
|
|
for (index, subview) in subviews.enumerated() {
|
|
let column = index % columns
|
|
if column == 0 && index > 0 {
|
|
rowY += rowHeight + spacing
|
|
rowHeight = 0
|
|
}
|
|
let size = subview.sizeThatFits(ProposedViewSize(width: cardWidth, height: nil))
|
|
frames.append(CGRect(x: CGFloat(column) * (cardWidth + spacing), y: rowY,
|
|
width: cardWidth, height: size.height))
|
|
rowHeight = max(rowHeight, size.height)
|
|
}
|
|
return frames
|
|
}
|
|
}
|