I'm trying to place these Text views as follows
When I try the .position()
modifier to manually center the "App title" precisely, that seems to work. However, its returned view takes up the entire available space and pushes the Text views for "Edit" and "..." completely out of the desired position.
struct SOPosition: View {
var body: some View {
HStack {
Text("App title")
.border(Color.blue)
.position(x: UIScreen.width / 2)
.border(Color.red)
Group {
Text("Edit")
Text("...")
}.border(.yellow)
.frame(alignment: .trailing)
}
Spacer()
}
} // SOPosition
Below is a screenshot for it
When I try to use .offset()
modifier, I get approximate result by tweaking the coordinate values. Is there a cleaner way which does not involve hard-coded values.
struct SOOffset: View {
var body: some View {
HStack {
Text("").frame(alignment: .leading)
Spacer()
Text("App title").offset(x: 40)
Spacer()
Group {
Text("Edit")
Text("...")
}.frame(alignment: .trailing).offset(x: -20)
}
Spacer()
}
} // SOOffset
Below is a screenshot for it
I would suggest showing the menu items in an overlay over the title, with trailing alignment. This way, if the title and the buttons have different heights, perhaps because the title uses a bigger font, they stay aligned in the vertical center.
When you want to have content fill the full width or height of the screen, you can either use a Spacer
to hog the unused space (as you are doing), or you can use .frame(maxWidth: .infinity, maxHeight: .infinity)
. Both techniques are valid and sometimes you will want to use one, sometimes the other. However, two advantages of using .frame
are:
Spacer
and other content (when used in a stack with non-zero spacing).Also, if you need the exact size of the screen then you should use a GeometryReader
. This works better for split screen on iPad. UIScreen.main.bounds
is deprecated anyway.
So here is an updated version of your example:
var body: some View {
VStack {
Text("App title")
.font(.largeTitle)
.border(Color.blue)
.frame(maxWidth: .infinity)
.overlay(alignment: .trailing) {
HStack {
Text("Edit")
Text("...")
}
}
.padding(.horizontal)
.border(.yellow)
Text("main content")
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}