如何在SwiftUI中为选项卡项目设置动画(选定时)?

时间:2019-07-30 11:25:24

标签: tabbar swiftui tabview

如何在SwiftUI中为选中的TabView标签栏项设置动画?

例如,为选定的项目添加.scaleEffect()动画,.spring() 或如下所示:

Example

这是我到目前为止尝试过的:

struct MyTabbedView: 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")
                            .font(self.enlargeIt1 ? .system(size: 30) : .system(size: 15) )
                            .animation(.interpolatingSpring(mass: 0.7, stiffness: 200, damping: 10, initialVelocity: 4))
                        Text("Music")
                    }
                }.tag(1)

            Text("Item 2")
                .onAppear {
                    self.enlargeIt1.toggle()
                    self.enlargeIt2.toggle()
                }
                .tabItem{
                    VStack{
                        Image(systemName: "music.mic")
                            .font(self.enlargeIt2 ? .system(size: 30) : .system(size: 15) )
                            .animation(.interpolatingSpring(mass: 0.7, stiffness: 200, damping: 10, initialVelocity: 4))
                        Text("Mic")
                    }
                }.tag(2)

        }
    }
}

结果是这样的:

enter image description here

我在名为 TestView 的单独视图中尝试了大约相同的代码:

struct TestView: View {
    @State var enlargeIt1 : Bool = false

    var body: some View {
        VStack{
            Image(systemName: "music.note")
                .font(self.enlargeIt1 ? .system(size: 30) : .system(size: 15) )
                .animation(.interpolatingSpring(mass: 0.7, stiffness: 200, damping: 10, initialVelocity: 4))
            Text("Music")
        }
        .onTapGesture {
            self.enlargeIt1.toggle()
        }

    }
}

这是结果:

TestView

我创建的TabView不能给出相同的结果怎么了?

2 个答案:

答案 0 :(得分:1)

有人创建了一个自定义TabView,可能会对您有所帮助。我相信您可以对其进行修改以满足您的需求。

  

受此concept启发的SwiftUI的BottomBar组件

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)
            }
        }
    }
}

答案 1 :(得分:1)

这里是标准TabView的可行方法(用于提供的代码快照)。

这个想法是使用可动画的修饰符来修饰使用过的SF图像的字体大小。

通过Xcode 11.4 / iOS 13.4测试

demo

// 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)

        }
    }
}