swiftswiftuisf-symbols

How to get rid of the padding of SF Symbol in SwiftUI


In example, I have a simple SwiftUI code that has an SF Symbol yet without any paddings. Here, I'm using .scaledToFit, so the image would be edge to edge (in future I'm gonna apply padding to it).

        VStack{
            Image(systemName: "drop")
                .resizable()
                .font(.largeTitle.weight(.ultraLight))
                .scaledToFit()
        }

Screenshot shows a small gap on the right side:

Screenshot shows a small gap on the right side

After using additional padding, the image still looks off. That gap becomes less but it's still noticable.

My expectation was that applying .scaledToFit would actually scale the image to fit the screen, and then I could use the padding.

Though even with padding the issue persists:

Though even with padding the issue persists.

I tried to use .aspectRatio(contentMode: .fit), and also different aspect ratios hoping that it could fix it.

Also the same issue persists even using the "square" SF Symbol (that likely excludes aspect ratio issue cuz square is 1:1) Though I fixed issue with square using .imageScale(.large)

Square without .imageScale(.large):

Square without .imageScale(.large)

Square with .imageScale(.large):

Square with .imageScale(.large)


Solution

  • It seems that when you use one of the named font sizes, there is sometimes a margin and sometimes not. But with some trial and error, a font size can usually be found which has no margin.

    My guess is that all of the following factors can have an impact on the margin:

    If you want to show a particular symbol with a particular font weight then it works best to use a .system font with a specific fixed size. This approach seems to be more resistant to different text size settings. However, finding the font size that works requires testing across different screen sizes. By using a process of binary chop, a size can usually be found quite quickly.

    Testing with Xcode 15.2 on an iPhone 15 simulator and iOS 17.2, I found that the "drop" image works with a font size of 15 (corresponding to .subheadline at the default text size):

    Image(systemName: "drop")
        .resizable()
        .font(.system(size: 15).weight(.ultraLight))
        .scaledToFit()
    

    Screenshot

    However, on an iPhone SE, you still see a margin. A size of 14.470234 works on the iPhone SE, but not on iPhone 15. So this one is difficult to get right across different devices.

    For the "square" image, I found that a font size of 14.0534608 works on iPhone 15, iPhone SE and iPad 10 gen:

    Image(systemName: "square")
        .resizable()
        .font(.system(size: 14.0534608).weight(.ultraLight))
        .scaledToFit()
    

    Screenshot

    I'm sure that there must be a way to calculate the font size from the screen size, but so far I haven't been able to work out the formula.

    Conclusions from all of this