How to animate tabbar items (on selection) in SwiftUI?

后端 未结 2 1374
离开以前
离开以前 2021-02-08 05:25

How can I animate Tabbar Items (of a TabView) on selection in SwiftUI?

for example give the selected item a .scaleEffect() with .spring()

相关标签:
2条回答
  • 2021-02-08 05:39

    Someone created a custom TabView that might be of help to you. I'm sure you could modify it to suit your needs.

    BottomBar component for SwiftUI inspired by this concept

    https://github.com/smartvipere75/bottombar-swiftui

    import SwiftUI
    import BottomBar_SwiftUI
    
    let items: [BottomBarItem] = [
        BottomBarItem(icon: "house.fill", title: "Home", color: .purple),
        BottomBarItem(icon: "heart", title: "Likes", color: .pink),
        BottomBarItem(icon: "magnifyingglass", title: "Search", color: .orange),
        BottomBarItem(icon: "person.fill", title: "Profile", color: .blue)
    ]
    
    struct BasicView: View {
        let item: BottomBarItem
    
        var detailText: String {
        "\(item.title) Detail"
    }
    
    var followButton: some View {
        Button(action: openTwitter) {
            VStack {
                Text("Developed by Bezhan Odinaev")
                    .font(.headline)
                    .color(item.color)
    
                Text("@smartvipere75")
                    .font(.subheadline)
                    .foregroundColor(.gray)
            }
        }
    }
    
    var destination: some View {
        Text(detailText)
            .navigationBarTitle(Text(detailText))
    }
    
    var navigateButton: some View {
        NavigationLink(destination: destination) {
            ZStack {
                Rectangle()
                    .fill(item.color)
                    .cornerRadius(8)
                    .frame(height: 52)
                    .padding(.horizontal)
    
                Text("Navigate")
                    .font(.headline)
                    .foregroundColor(.white)
            }
        }
    }
    
    func openTwitter() {
        guard let url = URL(string: "https://twitter.com/smartvipere75") else {
            return
        }
        UIApplication.shared.open(url, options: [:], completionHandler: nil)
    }
    
    var body: some View {
        VStack {
            Spacer()
    
            followButton
    
            Spacer()
    
            navigateButton
            }
        }
    }
    
    struct ContentView : View {
        @State private var selectedIndex: Int = 0
    
        var selectedItem: BottomBarItem {
            items[selectedIndex]
        }
    
        var body: some View {
            NavigationView {
                VStack {
                    BasicView(item: selectedItem)
                        .navigationBarTitle(Text(selectedItem.title))
                    BottomBar(selectedIndex: $selectedIndex, items: items)
                }
            }
        }
    }
    
    0 讨论(0)
  • 2021-02-08 05:43

    Here is possible approach for standard TabView (for provided code snapshot).

    The idea is to use animatable modifier for font size over used SF images.

    Tested with Xcode 11.4 / iOS 13.4

    // Animating font size
    struct AnimatableSFImage: AnimatableModifier {
        var size: CGFloat
    
        var animatableData: CGFloat {
            get { size }
            set { size = newValue }
        }
    
        func body(content: Self.Content) -> some View {
            content
                .font(.system(size: size))
        }
    }
    
    // helper extension
    extension Image {
        func animatingSF(size: CGFloat) -> some View {
            self.modifier(AnimatableSFImage(size: size))
        }
    }
    
    // Modified test code snapshot
    struct TestAnimatedTabBar: View {
        @State var enlargeIt1 = false
        @State var enlargeIt2 = true
    
        var body: some View {
            TabView {
                Text("Item 1")
                    .onAppear {
                        self.enlargeIt1.toggle()
                        self.enlargeIt2.toggle()
                    }
                    .tabItem{
                        VStack{
                            Image(systemName: "music.note")
                                .animatingSF(size: self.enlargeIt1 ? 30 : 15 )
                            Text("Music")
                        }.animation(.interpolatingSpring(mass: 0.7, 
                 stiffness: 200, damping: 10, initialVelocity: 4))
                    }.tag(1)
    
                Text("Item 2")
                    .onAppear {
                        self.enlargeIt1.toggle()
                        self.enlargeIt2.toggle()
                    }
                    .tabItem{
                        VStack{
                            Image(systemName: "music.mic")
                                .animatingSF(size: self.enlargeIt2 ? 30 : 15 )
                            Text("Mic")
                        }.animation(.interpolatingSpring(mass: 0.7, 
                 stiffness: 200, damping: 10, initialVelocity: 4))
                    }.tag(2)
    
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题