During experimenting with adding an image to the navigation bar I've noticed that an image isn't placed in the same spot as a system image or text. I have a ToolbarItem
that contains a VStack
with an image and text. The ToolbarItem
has an alignment of topBarLeading
so it is placed to the left. The VStack
has an alignment of center
so the image and the text are aligned at the center with each other. When I use a SF Symbol everything is in the location I would expect. When I change the symbol for an image that is resized and scaled to fit everything is offset further to the right than I expect. What causes this behavior and how can I get the image and text to the left?
This is how the toolbar item looks with an SF Symbol.
ToolbarItem(placement: .topBarLeading) {
VStack(alignment: .center) {
Image(systemName: "magnifyingglass")
.resizable()
.scaledToFit()
Text("Test text")
}
}
And this is how the toolbar item looks with an image. The image is taken from the magnifying glass page of Wikipedia.
ToolbarItem(placement: .topBarLeading) {
VStack(alignment: .center) {
Image(.magGlassRequest)
.resizable()
.scaledToFit()
Text("Test text")
}
}
It seems that the layout is based on the ideal size of the image, this being its natural dimensions.
The image you are using has dimensions 456×373. An iPhone screen in portrait orientation has a width of 393. So since the image is wider than the screen, it ends up being centered.
In landscape orientation, the width of an iPhone screen inside the safe area insets is 734. You then find, the image is no longer centered on the screen. However, it is still centered within a space of width 456, added to which is a leading offset of about 17 points (to give a gap to the left side).
The following body content can be used to demonstrate this:
VStack(alignment: .leading) {
HStack(spacing: 0) {
Color.orange
.frame(width: 17)
Color.yellow
.frame(maxWidth: 456)
.overlay { Divider() }
}
.frame(height: 100)
Text("hello")
.frame(maxWidth: .infinity)
Spacer()
}
To fix the alignment, try applying a different ideal size to constrain the image.
Image(.magGlassRequest)
.resizable()
.scaledToFit()
.frame(idealHeight: 40) // 👈 HERE
The text will then be left-aligned on the screen, with a gap to the leading edge of about 17 points (as above):