Reputation: 1527
I have Button
struct ContentView : View {
var body: some View {
HStack {
Button(action: {}) {
Text("MyButton")
.color(.white)
.font(Font.system(size: 17))
}
.frame(height: 56)
.background(Color.red, cornerRadius: 0)
}
}
}
But I want to pin it to supreview's edges (trailing to superview's trailing and leading). Like this:
HStack
doesn't help me, and it's expecting.
Fixed frame
or width equals UIScree.size
are not flexible solutions.
Upvotes: 60
Views: 55769
Reputation: 119178
From iOS 17, the correct way to do this is to use .containerRelativeFrame
modifier because using .infinity
width on the frame actually pushes the parent's frame to have an infinite width.
So it would be like:
Button(action: {}) {
Text("MyButton")
.foregroundStyle(.white)
.containerRelativeFrame(.horizontal) // π This should be inside the `label` parameter of the `button`. Otherwise it would be NOT touchable
.padding(-10) // π This is here to make space to the edges. Yes it should have a NEGATIVE value
}
.frame(height: 56)
.background(.red)
Upvotes: 6
Reputation: 2811
You need to use .frame(minWidth: 0, maxWidth: .infinity)
modifier
Add the next code
Button(action: tap) {
Text("Button")
.frame(minWidth: 0, maxWidth: .infinity)
.background(Color.red)
}
.padding(.horizontal, 20)
Padding modifiers will allow you to have some space from the edge.
Keep in mind that the order of modifiers is essential. Because modifiers are functions that are wrapping the view below (they do not change properties of views)
Upvotes: 110
Reputation: 1452
Here's a pure SwiftUI solution where you want to fill the width of the parent but constrain the height to an arbitrary aspect ratio (say you want square images):
Image("myImage")
.resizable()
.scaledToFill()
.frame(maxWidth: .infinity, maxHeight: .infinity)
.aspectRatio(16.0 / 9.0, contentMode: .fit)
Just replace 16.0 / 9.0 with whatever aspect ratio you want.
I spent about a day trying to figure this out because I didn't want to use GeometryReader or UIScreen.main.bounds (which isn't cross-platform)
Edit: Found an even simpler way.
Upvotes: 8
Reputation: 1048
Simple adding following to your code will make the button extend edge to edge. (You can add padding as well if you want)
.frame(minWidth: 0, maxWidth: .infinity)
The entire Button code will look like this:
struct ContentView : View {
var body: some View {
HStack {
Button(action: {}) {
Text("MyButton")
.color(.white)
.font(Font.system(size: 17))
}
.frame(minWidth: 0, maxWidth: .infinity)
.padding(.top, 8)
.padding(.bottom, 8)
.background(Color.red, cornerRadius: 0)
}
}
}
Upvotes: 5
Reputation: 22846
You can use GeometryReader
: https://developer.apple.com/documentation/swiftui/geometryreader
According to Apple:
This view returns a flexible preferred size to its parent layout.
It is a flexible solution, as it changes according to the parent layout changes.
Upvotes: 33
Reputation: 1527
I found one solution:
var body: some View {
Button(action: {}) {
HStack {
Spacer()
Text("MyButton")
.color(.white)
.font(Font.system(size: 17))
Spacer()
}
.frame(height: 56)
.background(Color.red, cornerRadius: 0)
}.padding(20)
}
But I'm not sure that it is the best. May be someone will find more elegant solution/
Upvotes: 2