2

How can i make a SwiftUI TabView with headers aligned to top rather than the bottom.

Thanks

TheWhiteSword
  • 115
  • 1
  • 10

1 Answers1

9

This is not directly supported by SwiftUI but you could make your own custom view and here is a simple example on how to do that:

struct ContentView: View {
    
    @State var selectedTab = Tabs.FirstTab
    
    var body: some View {
        VStack {            
            HStack {
                Spacer()
                VStack {
                    Image(systemName: "airplane")
                    .foregroundColor(selectedTab == .FirstTab ? Color.red : Color.black)
                    Text("First tab")
                }
                .onTapGesture {
                    self.selectedTab = .FirstTab
                }
                Spacer()
                VStack {
                    Image(systemName: "person.fill")
                        .foregroundColor(selectedTab == .SecondTab ? Color.red : Color.black)
                    Text("Second tab")
                }
                .onTapGesture {
                    self.selectedTab = .SecondTab
                }
                Spacer()
                VStack {
                    Image(systemName: "cart.fill")
                        .foregroundColor(selectedTab == .ThirdTab ? Color.red : Color.black)
                    Text("Third tab")
                }
                .onTapGesture {
                    self.selectedTab = .ThirdTab
                }
                Spacer()
            }
            .padding(.bottom)
            .background(Color.green.edgesIgnoringSafeArea(.all))
            
            Spacer()
            
            if selectedTab == .FirstTab {
                FirstTabView()
            } else if selectedTab == .SecondTab {
                SecondTabView()
            } else {
                ThirdTabView()
            }
        }
    }
}

struct FirstTabView : View {
    
    var body : some View {
        VStack {
            Text("FIRST TAB VIEW")
        }
    }
}

struct SecondTabView : View {
    
    var body : some View {
        Text("SECOND TAB VIEW")
    }
}

struct ThirdTabView : View {
    
    var body : some View {
        Text("THIRD TAB VIEW")
    }
}

enum Tabs {
    case FirstTab
    case SecondTab
    case ThirdTab
}

NOTE: I haven't put much effort in aligning the tabs perfectly and used Spacers for simplicity (because this is not relevant to the question). Also I have put all the code so that you could create new empty project and copy-paste it to try and understand how it works.

Lets go through it:

  1. The Tabs enum is created for simplicity
  2. The selectedTab variable is keeping track of which tab is currently selected
  3. I am using if-else construction to display the selected view (as of SwiftUI 2.0 there is also a switch-statement, but since you didn't specify what versions are you using I am using if-else)
  4. The tab view itself is nothing more than Image & Text views aligned to look like the TabView
  5. The foregroundColor modifier using ternary operator is simulating TabView's accent color
  6. When tapped, each Text + Image combination (which replaces buttons on the normal TabView) changes the state to select its view as visible (you could also use buttons with action instead of .onTapGesture I used this for the simplicity of the example)

Here is the result: Result

DI.dev
  • 457
  • 2
  • 13
  • Just would to ask, is there away to do the same by using the TabView such as alignement property and so on. – TheWhiteSword Jul 16 '20 at 13:02
  • @TheWhiteSword As I said in my answer this is currently not supported in SwiftUI - so no there is no way. – DI.dev Jul 16 '20 at 13:32