I want two equally sized buttons. I thought to be efficient using the Group
type to set the minWidth
and maxWidth
on both the buttons, like so:
HStack(spacing: 0) {
Group {
Button {
} label: {
Text("One")
.padding()
}
.background(.black)
.tint(.white)
Button {
} label: {
Text("Two")
.padding()
}
.background(.white)
.tint(.black)
}
.frame(minWidth: 0, maxWidth: .infinity) // <-
}
.background(.orange)
But this doesn't work. The buttons stay their intrinsic content size. To make them take up half of the space, I have to set the .frame on the buttons individually, like so:
Button {
} label: {
Text("One")
.padding()
}
.frame(minWidth: 0, maxWidth: .infinity) // <-
.background(.black)
.tint(.white)
Am I missing some limitations of the Group
Type? I thought it would apply .frame()
to both?
It certainly does something, because adding it to one Button
AND the Group,
gives desired behavior for that one Button
already.
The issue is not with the Group
but with the order of the modifiers. The order is very important in SwiftUI as it dictates how views are rendered and can produce different outcomes by just flipping two modifiers around. In your case, you are applying the frame
modifier after the background
modifier which is why you are seeing this result:
To explain, these two snippets are effectively the same and demonstrates what Group
is doing:
Group {
Button {
} label: {
Text("One")
.padding()
}
.background(.black)
.tint(.white)
Button {
} label: {
Text("Two")
.padding()
}
.background(.white)
.tint(.black)
}
.frame(minWidth: 0, maxWidth: .infinity) // <-
Button {
} label: {
Text("One")
.padding()
}
.background(.black)
.tint(.white)
.frame(minWidth: 0, maxWidth: .infinity) // <-
Button {
} label: {
Text("Two")
.padding()
}
.background(.white)
.tint(.black)
.frame(minWidth: 0, maxWidth: .infinity) // <-
What you really want is this:
which can be achieved by applying the frame
modifier before the background
modifier, like this:
Button {
} label: {
Text("One")
.padding()
}
.frame(minWidth: 0, maxWidth: .infinity) // <-
.background(.black)
.tint(.white)
Button {
} label: {
Text("Two")
.padding()
}
.frame(minWidth: 0, maxWidth: .infinity) // <-
.background(.white)
.tint(.black)
This has to be done individually as using Group
can't fulfil that. What you can do instead is create a custom button style with this max frame (and anything else you want) and then apply that to the Group
or HStack
.