LayoutValueKey attaches a per-view parameter that a custom Layout reads during sizing and placement. The worked example lets each child of a flow layout choose its own anchor point.
Declare the Key and a Sugar Modifier
A key only needs a defaultValue, which SwiftUI uses for views that set nothing. A small View extension hides the verbose layoutValue call.
struct UnitPointKey: LayoutValueKey {
static var defaultValue: UnitPoint = .center
}
extension View {
func anchor(_ anchor: UnitPoint) -> some View {
layoutValue(key: UnitPointKey.self, value: anchor)
}
}
Attach Values at the Call Site
Children opt in individually; the rest fall back to the default.
FlowLayout {
Text("Hello")
.font(.largeTitle)
.anchor(.bottom)
Text("World")
.font(.title)
.anchor(.top)
Text("!!!")
.font(.title3)
}
Read the Value Through the Subview Subscript
Inside the layout, subscript the Subview proxy with the key type. Here the value feeds the anchor argument of place.
func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout Cache) {
var lineX = bounds.minX
var lineY = bounds.minY
var lineHeight: CGFloat = 0
for index in subviews.indices {
if lineX + cache.sizes[index].width > (proposal.width ?? 0) {
lineY += lineHeight
lineHeight = 0
lineX = bounds.minX
}
let anchor = subviews[index][UnitPointKey.self]
subviews[index].place(
at: CGPoint(
x: lineX + cache.sizes[index].width / 2,
y: lineY + cache.sizes[index].height / 2
),
anchor: anchor,
proposal: ProposedViewSize(cache.sizes[index])
)
lineHeight = max(lineHeight, cache.sizes[index].height)
lineX += cache.sizes[index].width
}
}
The same mechanism carries any per-child value: a flex factor, a priority, a span. It is the layout-system twin of PreferenceKey, flowing from the child to its layout container.