Hi
I really liked the video by Paul Lettieri, creating a replacement for HStack that gives equal width to each, so I wrote one for my app. But the app doesn't compile for me. It gives me "Trailing closure passed to parameter of type 'HorizontalAlignment' that does not accept a closure" against the top VStack, not the place where the equal lengths HStack replacement appears.
This is my version of his struct:
extension LayoutSubviews {
func maxSize() -> CGSize {
let subviewSizes = map { $0.sizeThatFits(.unspecified) }
return subviewSizes.reduce(CGSize.zero) { CGSize(width: Swift.max($0.width, $1.width), height: Swift.max($0.height, $1.height)) }
}// maxSize()
func spacing() -> [Double] {
return indices.map { index in
guard index < count - 1 else { return 0.0 }
return self[index].spacing.distance(to: self[index + 1].spacing, along: .horizontal)
}
}// spacing()
}// extension LayoutSubviews
struct EqualWidthHStack: Layout {
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
let maxsize = subviews.maxSize()
let totalSpacing = subviews.spacing().reduce(0) { $0 + $1 }
return CGSize(width: maxsize.width * Double(subviews.count) + totalSpacing, height: maxsize.height)
}// sizeThatFits
func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
let maxsize = subviews.maxSize()
let spacing = subviews.spacing()
let sizeProposal = ProposedViewSize(width: maxsize.width, height: maxsize.height)
var x = bounds.minX + maxsize.width / 2
for index in subviews.indices {
subviews[index].place(at: CGPoint(x: x, y: bounds.midX), anchor: .center, proposal: sizeProposal)
x += maxsize.width + spacing[index]
}
}// placeSubviews
}// EqualWidthHStack
I wrote this trivial View to test it:
struct ContentView: View {
var body: some View {
VStack {
HStack {
Button("Hi") { print("Hi!") }
Button("Hello") { print("Hello!") }
Button("Good evening") { print("Good evening!") }
}
EqualWidthHStack {
Button("Hi") { print("Hi!") }
Button("Hello") { print("Hello!") }
Button("Good evening") { print("Good evening!") }
}
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
}
}
}
I'm using Version 14.0 beta 2 (14A5229c) of Xcode. I was having a problem with the exact same message in another app with a much more complex main view.
I hope someone can tell me what to do or what is going on here.
Regards,
Mark
A lot of people have been experiencing different behaviours with the new Layout
API and they each have different solutions.
Resolved in iOS & iPadOS 16 beta 2, passing multiple children to a custom Layout
now compiles. This means that a Group
or another container is no longer required.
The other issue arises from how the layout views are created under the hood.
Two solutions for this are either wrapping the layout name in parentheses:
(CustomLayout()) {
Text("Hello, World")
Text("Hello, World")
}
or creating an initialiser for the custom Layout
that accepts no parameters:
init() {}
...
CustomLayout {
Text("Hello, World")
Text("Hello, World")
}