I came across the same problem as you: SF Symbols are not reporting the correct content size on iOS 13. (Though, it is fixed on iOS 14 and above.)
The problem with using UIImage
as proposed in Matteo Pacinis solution is the poor compatibility with the SwiftUI dynamics: foreground color and font size (and dynamic type!) are not simply taken from the current SwiftUI context but have to be duplicated into the UIImage
configuration (using UIImage(systemName:, withConfiguration:)
) wich is often not practical. (see hackingwithswift.com for how to use this).
Looking at the problem above I propose the following solution:
HStack(alignment: .center, spacing: 10.0) {
Image(systemName: "cloud.sun")
.hidden()
.overlay(
Image(systemName: "cloud.sun")
.resizable()
.aspectRatio(contentMode: .fill)
.background(Color.red)
)
Image(systemName: "cloud")
.hidden()
.overlay(
Image(systemName: "cloud")
.resizable()
.aspectRatio(contentMode: .fill)
.background(Color.yellow)
)
Image(systemName: "cloud.bolt")
.hidden()
.overlay(
Image(systemName: "cloud.bolt")
.resizable()
.aspectRatio(contentMode: .fill)
.background(Color.pink)
)
Text("Text")
.background(Color.green)
}
.background(Color.gray)
.font(.title)
It looks like a lot of code duplication but it has the advantage, that the symbols scale according to your font
, respect the foregroundColor
modifier and align according to your desired alignment
Output:
But there is still some issue with this approach: the image still has not the correct intrinsic size, the symbols are simply drawn "nicely centered". This means that the height of the HStack
still depends of the height of the Text
element.
If you simply want to draw the symbols in .largeTitle
font and the text in .body
font, the result would look like below possibly causing overlapping with neighbouring views:
I will still investigate further to find a solution ensuring the correct view size, as this really annoys me.
.frame(height: 32)
? Makes no difference. :/ – Activity