1

The question might look familiar, but I went through all solutions on this topic but none had a working approach for the latest versions of SwiftUI and iOS.

So here is my tab view, I am trying to animate when switching between the tabs. I tried binding animations by adding animation to the binding and that does not work. I also tried attaching the onChange modifier on the TabView itself which prints the correctly selected tab but it does not animate so neither approach works could someone point to the correct implementation of this?

struct MainTabScreen: View {
  @State private var selectedTab = 0

  var body: some View { 
       // The binding animation does not animate
       TabView (selection: $selectedTab.animation(
        .easeInOut(duration: 1.0))
    ) {
            Home()
                .tabItem {
                    Image(systemName: "house")
                    Text("Home")
                }
                .tag(0)
            Dollar()
                .tabItem {
                    Image(systemName: "dollarsign.circle")
                    Text("Dollar")
                }
                .tag(1)
            Menu()
                .tabItem {
                    Image(systemName: "plus")
                    Text("Menu")
                }
                .tag(2)
        }
        .onChange(of: selected, perform: { tab in
            print("TAPPED ON :\(tab)") // prints correct tab
            withAnimation(.easeInOut(duration: 2)) {
                selectedTab = tab // does not animate
            }
        })
   }
}

Most solutions online advise using .animation(.easeInOut) to the tab view itself, but this is now deprecated. Looking for a solution that works with iOS 15 and Swift 5.

AD Progress
  • 4,190
  • 1
  • 14
  • 33
Siva2789
  • 79
  • 6
  • 3
    Not clear what/how exactly do you want TabView animates. – Asperi Jun 04 '22 at 02:57
  • They use dedicated hosting controller for each tab ... it is simpler to completely write TabView from scratch in pure-SwiftUI than make this "thing" normally animatable. – Asperi Jun 28 '22 at 18:11
  • What you looking about animation? it make no better app with having animation in change of tabs, are looking to scale or fade or what??? – ios coder Jun 29 '22 at 01:40
  • I am looking to add a 3drotation effect when switching tabs or cross dissolve. – AD Progress Jun 30 '22 at 08:58
  • @Siva2789 How did you animate the tab bar item at the end? I'm trying to add some animation when the tab item is selected (and currently using Apple's default TabBar), so I wonder how you solved it. – Yuuu Jul 27 '23 at 06:35

1 Answers1

4

SwiftUI.TabView is one of those Views that just offer the basic Apple look.

You can easily substitute that SwiftUI.TabView with your own so you can add any animations, transitions, colors that work for you app.

import SwiftUI

struct MainTabScreen: View {
    @State private var selectedTab: Tabs = .home
    
    var body: some View {
        VStack{
            //Present only the View that is selected
            selectedTab.view()
            // You can also apply transitions if you want
            //.transition(.slide)
            //Have the selected View take up all the available space
                .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
            //This is the "TabView"
            HStack{
                ForEach(Tabs.allCases, id:\.rawValue){ tab in
                    tab.label()
                    //Change the color for the selected case
                        .foregroundColor(selectedTab == tab ? Color.blue : nil)
                    //Select the animation and change the tab using your desired abimation
                        .onTapGesture {
                            withAnimation(.easeInOut){
                                selectedTab = tab
                            }
                        }
                    //Stretch the Views so they take up the entire bottom
                        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
                    
                }
            }
            //Set the height of the TabView
            .frame( height: 80, alignment: .center)
        }
        
    }
    //Enum that keeps track of the New TabView's Views
    enum Tabs:String,CaseIterable,CustomStringConvertible{
        case home
        case dollar
        case menu
        ///Formatted name for the View
        var description: String{
            rawValue.capitalized
        }
        ///Image that represents the View
        @ViewBuilder func image() -> some View{
            switch self {
            case .home:
                Image(systemName: "house")
            case .dollar:
                Image(systemName: "dollarsign.circle")
            case .menu:
                Image(systemName: "plus")
            }
        }
        ///Primary View for the tab
        @ViewBuilder func view() -> some View{
            switch self {
            case .home:
                Text("Home()")
            case .dollar:
                Text("Dollar()")
            case .menu:
                Text("Menu()")
            }
        }
        ///Label for the TabView
        @ViewBuilder func label() -> some View{
            switch self {
            default:
                VStack{
                    image()
                    Text(description)
                }
            }
        }
    }
}

struct MainTabScreen_Previews: PreviewProvider {
    static var previews: some View {
        MainTabScreen()
    }
}

enter image description here

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