Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
// Determine the alignment of every view in the ZStack
func zStackViews(_ geometry: GeometryProxy) -> some View {
// These are used to track the current horizontal and vertical position
// in the ZStack. As a new text or link is added, horizontal is decreased.
// When a new line is required, vertical is decreased & horizontal is reset to 0.
var horizontal: CGFloat = 0
var vertical: CGFloat = 0
// Determine the alignment for the view at the given index
func forEachView(_ index: Int) -> some View {
let numberOfViewsInContent: Int
let view: AnyView
// Determine the number of views in the Content at the given index
switch content[index] {
case .text(let text):
numberOfViewsInContent = text.count
view = AnyView(text)
case .link(let link):
numberOfViewsInContent = 1
view = AnyView(link)
}
var numberOfViewsRendered = 0
// Note that these alignment guides can get called multiple times per view
// since ContentText returns a ForEach
return view
.alignmentGuide(.leading, computeValue: { dimension in
numberOfViewsRendered += 1
let viewShouldBePlacedOnNextLine = geometry.size.width < -1 * (horizontal - dimension.width)
if viewShouldBePlacedOnNextLine {
// Push view to next line
vertical -= dimension.height
horizontal = -dimension.width
return 0
}
let result = horizontal
// Set horizontal to the end of the current view
horizontal -= dimension.width
return result
})
.alignmentGuide(.top, computeValue: { _ in
let result = vertical
// if this is the last view, reset everything
let isLastView = index == content.indices.last && numberOfViewsRendered == numberOfViewsInContent
if isLastView {
vertical = 0
horizontal = 0
numberOfViewsRendered = 0
}
return result
})
}
return ForEach(content.indices, content: forEachView)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment