SwiftUI Custom TabBar

Created At: 2023-01-31 18:25:59 Updated At: 2023-02-02 01:10:25

Creating custom TabBar in SwiftUI is relatively easy. We need to use some of it's builtin views and stack.  Previoulsy we have seen we can use TabView for image slider

Here we will use TabView to create cutom TabBar with content on the screen. To be able to create a custom TabBar in SwiftUI, we need to combine our VStack with Button() view. 

Of course we will put Button() view inside HStack and then put the HStack inside VStack. Why? Because we need to buttons horizontally. Actual button click would trigger TabView with content. Let's work on the buttons first.

   HStack {
                tabButton(title: "One", tag: 1)
                tabButton(title: "Two", tag: 2)
                tabButton(title: "Three", tag: 3)
            }
            .padding(.top)
            .font(.headline)

Here we created a custom tabButton() struct. This struct will create our buttons. In this struct we also provide a argument name title and tag. The last argument will help us know which button is being tapped.

More about our tabButton() struct. This struct also does animation when click. For this animation we needed a global variable. We declared it at the top.

@State private var selectedTab = 1

The variable selectedTab would help us to maintain the state of button click, it means we have to remember which button has been clicked. That's why we did @State before it. tabButton() will have two parameters to be received. Tab name and a tag.

Our variable selectedTab and tag would work together to identify which button has been clicked. See how selectedTab and SwiftUI tag() function work together to find a clicked button and connect the button with Tab Bar view.

Now see our TabView() it self. Inside TabView, we have three views showing Text() and each of them has SwiftUI tag() function added. Without this, you can not remember which button has been click. We need this because we need to each time you tap on button, it needs to find the TabView for corresponding button click.

Here's the code for TabView

TabView(selection: $selectedTab) {
        Text("First Tab").tag(1)
        Text("Second Tab").tag(2)
        Text("Third Tab").tag(3)
}

See here, we have tag() function. With this, whenever you click on a button, then the button click will assign a new value to button using selectedTab varaible.  Since it's a global variable, the value is reflected inside TabView(). Then then tag() can get and match the value with selectedTab and shows on the screen the right content for the tab.

Complete code

import SwiftUI

struct ContentView:View{
    var body:some View{
        //SliderView()
       
        ContenttView()
    }
}



struct ContenttView: View {
    
    @State private var selectedTab = 1
    
    var body: some View {
        
        VStack(alignment: .leading, spacing: 0) {
      
            HStack {
                tabButton(title: "One", tags: 1)
                tabButton(title: "Two", tags: 2)
                tabButton(title: "Three", tags: 3)
            }
            .padding(.top)
            .font(.headline)
            TabView(selection: $selectedTab) {
                Text("First Tab").foregroundColor(.white).font(.largeTitle).tag(1)
                Text("Second Tab").foregroundColor(.white).font(.largeTitle).tag(2)
                Text("Third Tab").foregroundColor(.white).font(.largeTitle).tag(3)
            }
            .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)).frame(height: 200)
            .background(.teal).padding()
            Spacer()
        }
        
    }
    
    func tabButton(title: String, tags: Int) -> some View {
        VStack {
            Button(title) { withAnimation { selectedTab = tags } }
            .frame(maxWidth: .infinity)
            .foregroundColor(selectedTab == tags ? .teal : .secondary)
            
            Color(selectedTab == tags ? .blue : .clear)
                .frame(height: 4)
                .padding(.horizontal)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Comment

Add Reviews