Created
November 21, 2019 23:44
-
-
Save cjnevin/418b87124499a0221b072b5db1b45f95 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
struct WrappingStack<T: View>: UIViewRepresentable { | |
@Binding var views: [T] | |
let spacing: CGFloat | |
func makeUIView(context: Context) -> WrappingStackView { | |
let view = WrappingStackView() | |
view.spacing = spacing | |
return view | |
} | |
func updateUIView(_ uiView: WrappingStackView, context: Context) { | |
uiView.views = views.map { UIHostingController(rootView: $0).view } | |
} | |
} | |
class WrappingStackView: UIStackView { | |
var views: [UIView] = [] { | |
didSet { | |
render() | |
} | |
} | |
override func layoutSubviews() { | |
super.layoutSubviews() | |
render() | |
} | |
private func removeAllArrangedSubviews() { | |
arrangedSubviews.forEach { | |
self.removeArrangedSubview($0) | |
$0.removeFromSuperview() | |
} | |
} | |
private func addRow() -> UIView { | |
let view: UIView = UIView() | |
addArrangedSubview(view) | |
return view | |
} | |
private func render() { | |
axis = .vertical | |
removeAllArrangedSubviews() | |
var row = addRow() | |
var currentY: CGFloat = 0 | |
var copy = views | |
while !copy.isEmpty { | |
let column = copy.removeFirst() | |
var currentX = row.subviews.reduce(CGFloat(row.subviews.count) * spacing) { current, view in | |
current + view.intrinsicContentSize.width | |
} | |
if currentX + spacing + column.intrinsicContentSize.width > frame.width { | |
currentX = 0 | |
currentY += column.intrinsicContentSize.height + spacing | |
row = addRow() | |
} | |
row.addSubview(column) | |
column.frame = CGRect(origin: .init(x: currentX, y: currentY), size: column.intrinsicContentSize) | |
} | |
} | |
} | |
struct TagView: View { | |
let text: String | |
var body: some View { | |
Text(text) | |
.lineLimit(1) | |
.padding(10) | |
.background(Color.blue) | |
.foregroundColor(Color.white) | |
.cornerRadius(15) | |
} | |
} | |
struct TagCloudView: View { | |
@Binding var texts: [String] | |
var body: some View { | |
WrappingStack(views: .constant(texts.map(TagView.init)), spacing: 5) | |
} | |
} | |
struct TagCloudView_Previews: PreviewProvider { | |
static var previews: some View { | |
TagCloudView(texts: .constant([ | |
"alcohol", "stress", "binge", "lazy", "running", "car", "cycling", "boating", "mountain biking", "bus", "spelunking" | |
])).padding(10) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment