【问题标题】:How to animate tabbar items (on selection) in SwiftUI?如何在 SwiftUI 中为标签栏项目(选择时)设置动画?
【发布时间】:2019-12-07 18:43:33
【问题描述】:

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

例如给选定的项目一个.scaleEffect() 和.spring() 动画 或如下:

这是我迄今为止尝试过的:

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)

        }
    }
}

结果是这样的:

我在名为 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()
        }

    }
}

结果如下:

我创建的TabView 没有给出相同的结果有什么问题?

【问题讨论】:

  • “选项卡视图仅支持文本、图像或图像后跟文本类型的选项卡项。传递任何其他类型的视图会导致可见但为空的选项卡项。”听起来您无法真正修改选项卡项的样式。 source
  • 请说得更具体一点,您到底想要/期望发生什么?
  • @kontiki 我的朋友 kontiki 大脑????有什么意见吗?

标签: tabbar swiftui tabview


【解决方案1】:

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

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

使用 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)

        }
    }
}

【讨论】:

  • 如果你把动画放到整个tabView,即使是视图的内容例如HomeView()也会被动画化。
  • @airsoftFreak,你是对的,它是中间测试留下的。已更新。
  • 从 Xcode 13 for iOS15 开始,在模拟器上测试,这不再起作用。
【解决方案2】:

有人创建了一个自定义TabView,可能对您有所帮助。我相信你可以修改它以满足你的需要。

受concept启发的 SwiftUI 的底部栏组件

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

【讨论】:

    猜你喜欢
    • 2019-03-29
    • 2023-03-24
    • 2012-11-06
    • 1970-01-01
    • 1970-01-01
    • 2011-11-21
    • 2018-05-27
    • 2017-04-08
    • 1970-01-01
    相关资源
    最近更新 更多