51 lines
2.3 KiB
Swift
51 lines
2.3 KiB
Swift
import SwiftUI
|
|
|
|
//自动换行
|
|
//https://stackoverflow.com/questions/58842453/hstack-with-wrap RelativeJoe的回答
|
|
public struct OverflowGrid: Layout {
|
|
private var horizontalSpacing: CGFloat
|
|
private var vericalSpacing: CGFloat
|
|
public init(horizontalSpacing: CGFloat, vericalSpacing: CGFloat? = nil) {
|
|
self.horizontalSpacing = horizontalSpacing
|
|
self.vericalSpacing = vericalSpacing ?? horizontalSpacing
|
|
}
|
|
public func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
|
|
let height = subviews.max(by: {$0.dimensions(in: proposal).height > $1.dimensions(in: proposal).height})?.dimensions(in: proposal).height ?? 0
|
|
var rows = [CGFloat]()
|
|
subviews.indices.forEach { index in
|
|
let rowIndex = rows.count - 1
|
|
let subViewWidth = subviews[index].dimensions(in: proposal).width
|
|
guard !rows.isEmpty else {
|
|
rows.append(subViewWidth)
|
|
return
|
|
}
|
|
let newWidth = rows[rowIndex] + subViewWidth + horizontalSpacing
|
|
if newWidth < proposal.width ?? 0 {
|
|
rows[rowIndex] += (rows[rowIndex] > 0 ? horizontalSpacing: 0) + subViewWidth
|
|
}else {
|
|
rows.append(subViewWidth)
|
|
}
|
|
}
|
|
let count = CGFloat(rows.count)
|
|
return CGSize(width: rows.max() ?? 0, height: count * height + (count - 1) * vericalSpacing)
|
|
|
|
}
|
|
public func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
|
|
let height = subviews.max(by: {$0.dimensions(in: proposal).height > $1.dimensions(in: proposal).height})?.dimensions(in: proposal).height ?? 0
|
|
guard !subviews.isEmpty else {return}
|
|
var x = bounds.minX
|
|
var y = height/2 + bounds.minY
|
|
subviews.indices.forEach { index in
|
|
let subView = subviews[index]
|
|
x += subView.dimensions(in: proposal).width/2
|
|
subviews[index].place(at: CGPoint(x: x, y: y), anchor: .center, proposal: ProposedViewSize(width: subView.dimensions(in: proposal).width, height: subView.dimensions(in: proposal).height))
|
|
x += horizontalSpacing + subView.dimensions(in: proposal).width/2
|
|
if x > bounds.width {
|
|
x = bounds.minX
|
|
y += height + vericalSpacing
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|