add two images and one Label in TabBar, SwiftUI

Viewed 58

I have to implement a custom tabbar. I have attached the UI of required TabBar.

TabBar Image

I need to add two image inside the each TabBar Item. First one is above the text and second one is at bottom of text. I have tried 3 different method but each time TabBar is showing the same result.

 // method one not working
        HideNavbarOf(view: HomeView())
            .tabItem {
                
                ZStack {
                    
                    Image(ImageName.diamondFill.rawValue)
                        .resizable()
                        .scaledToFit()
                        .frame(width: 25)
                    
                    Text("Subscription")
                        .font(.custom(Popins.regular.rawValue, size: 11))
                        .foregroundColor(.white)
                    
                    Image(ImageName.tapSelected.rawValue)
                        .resizable()
                        .scaledToFit()
                        .frame(width: 25)
                        
                }
                
                
            }
            .tag(0)
        // method two not working
        HideNavbarOf(view: Text("AskQuestion"))
        
            .tabItem {
                
                ZStack {
                    Label {
                        Text("Shop")
                            .font(.custom(Popins.regular.rawValue, size: 11))
                            .foregroundColor(.white)
                    } icon: {
                            Image(ImageName.storeLine.rawValue)
                                .resizable()
                                .scaledToFit()
                                .frame(width: 10, height: 10)
                            
                    }
                    
                    Image(ImageName.tapSelected.rawValue)
                        .resizable()
                        .scaledToFit()
                        .frame(width: 10, height: 10)
                }
                
                
            }
            .tag(1)
        // method three not working
        HideNavbarOf(view: Text("Chat"))
        
            .tabItem {
                Label {
                    Text("Home")
                        .font(.custom(Popins.regular.rawValue, size: 11))
                        .foregroundColor(.white)
                } icon: {
                    VStack {
                        Image(ImageName.homeLine.rawValue)
                            .resizable()
                            .scaledToFit()
                            .frame(width: 10, height: 10)
                        
                        Image(ImageName.tapSelected.rawValue)
                            .resizable()
                            .scaledToFit()
                            .frame(width: 10, height: 10)

                    }
                }
            }
            .tag(2)

Below is the image of tabBar Item after these methods. There is no effect of any method, tabItem is only considering the first one Image and Label.

Preview

How Can I achieve the required UI that have Image at top and bottom and a text in middle.

1 Answers

Default TabView bar has equal-sized tab items, so a possible approach is to use overlay with some extra "selector" indicator image that changes its location with TabView selection (possibly even with matched effect animation).

Tested with Xcode 13.4 / iOS 15.5

demo

Main part:

    .overlay(selector, alignment: .bottom)
    .edgesIgnoringSafeArea(.bottom)
}

private var selector: some View {
    HStack(spacing: 0) {
        ForEach(0..<numberOfTabs, id: \.self) { i in
            Color.clear.overlay(Group{
                if i == selection {
                    Image(systemName: "arrowtriangle.up.fill")
                        .resizable().aspectRatio(contentMode: .fit)
                        .matchedGeometryEffect(id: "mark", in: ns)
                        .foregroundColor(.blue)
                }
            }).frame(maxWidth: .infinity)
        }
    }

Complete code on GitHub

Related