8

I have a TabView that shall show a .tabItem with a custom image (not an Image(systemName:)):

@ObservedObject var model: MaintainAreaSelectionModel = MaintainAreaSelectionModel()


... 

    var body: some View {

        VStack {
            Image("Timeline")

            TabView(selection: $model.lastSelectedMaintainAreaIndex) {

                SomeView()
                    .tabItem({

                            Image("Timeline")
                            Text("Title")
                    })
                    .tag(0)
            }
        }
    }
...

While the first Image shows the icon correctly, the second Image just shows a gray circle.

The image is part of the Assets catalog, I tried it with PDF vector images as well as with dedicated Bitmaps for all sizes (according to Apple's HIG) - no difference, always gray.

Any idea what's happening here? Are there perhaps any undocumented constraints that the image must fulfill to work as tabItem?

Hardy
  • 4,344
  • 3
  • 17
  • 27

3 Answers3

4

I found that I can display a custom image in a tab item with SwiftUI, but only if the source is a UIImage and the modifiers must be set on the UIImage, as they have no effect when applied to the SwiftUI Image constructed from UIImage.

This is the component that I'm using to display a rounded fixed sized image on the tab tray. It resizes the supplied UIImage, clips it with a circle and the sets the rendering mode to original, otherwise it's just grey.

struct TabIcon: View {
    var icon: UIImage
    var size: CGSize = CGSize(width: 30, height: 30)

    // Based on https://stackoverflow.com/a/32303467
    var roundedIcon: UIImage {
        let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: self.size)
        UIGraphicsBeginImageContextWithOptions(self.size, false, 1)
        defer {
            // End context after returning to avoid memory leak
            UIGraphicsEndImageContext()
        }

        UIBezierPath(
            roundedRect: rect,
            cornerRadius: self.size.height
            ).addClip()
        icon.draw(in: rect)
        return UIGraphicsGetImageFromCurrentImageContext()!
    }

    var body: some View {
        Image(uiImage: roundedIcon.withRenderingMode(.alwaysOriginal))
    }
}
Agost Biro
  • 2,709
  • 1
  • 20
  • 33
0

TabView Images have to be a very specific size/format for them to work

https://developer.apple.com/design/human-interface-guidelines/components/navigation-and-search/tab-bars/

If you download the SF Symbols app from the Apple Website you can export a template so you can create your own symbol that behaves just like the

Image(systemName: "")

Image. Just open the SF symbols app click on an image that resembles your image (for visual reference) the go to File>Export Symbol you can them mimic the image.

Once you edit the exported svg to match your specifications you can just drag it into assets.

Then you can use Image("yourSVGfilename")

lorem ipsum
  • 21,175
  • 5
  • 24
  • 48
-2

First of all, you have to set Image to render as Original Image from Assets.

enter image description here

Then set renderMode in tabbar Image as a .original

TabView(selection: $model.lastSelectedMaintainAreaIndex) {

            SomeView()
                .tabItem({

                        Image("Timeline").renderingMode(.original)
                        Text("Title")
                })
                .tag(0)
        }
Vishal Patel
  • 717
  • 6
  • 11