如何在 SwiftUI 中为 navigationBarHidden 设置动画?

How to animate navigationBarHidden in SwiftUI?

struct ContentView: View {
    @State var hideNavigationBar: Bool = false
    
    var body: some View {
        NavigationView {
            ScrollView {
                VStack {
                    Rectangle().fill(Color.red).frame(height: 50)
                        .onTapGesture(count: 1, perform: {
                            withAnimation {
                                self.hideNavigationBar.toggle()
                            }
                        })
                    VStack {
                        ForEach(1..<50) { index in
                            HStack {
                                Text("Sample Text")
                                Spacer()
                            }
                        }
                    }
                }
            }
            .navigationBarTitle("Browse")
            .navigationBarHidden(hideNavigationBar)
        }
    }
}

当您点击红色矩形时,它会将导航栏弹开。我以为 withAnimation{} 会解决这个问题,但事实并非如此。在 UIKit 你会做这样的事情 navigationController?.setNavigationBarHidden(true, animated: true).

在 xCode 12 beta 6 和 xCode 11.7

中测试

您可以尝试使用

.navigationBarHidden(hideNavigationBar).animation(.linear(duration: 0.5)) 而不是 .navigationBarHidden(hideNavigationBar)

并将self.hideNavigationBar.toggle()移出动画块。如果您使用上述方法隐藏带动画的导航栏,则不需要。

我仍在学习 SwiftUI 中的动画,但在这个阶段,我知道您必须为父视图设置动画。

所以你的代码会变成...

struct ContentView: View {

    @State var hideNavigationBar: Bool = false
    
    var body: some View {
        NavigationView {
            ScrollView {
                VStack {
                    Rectangle().fill(Color.red).frame(height: 50)
                        .onTapGesture(count: 1) {
                            self.hideNavigationBar.toggle()
                        }
                    VStack {
                        ForEach(1..<50) { index in
                            HStack {
                                Text("Sample Text")
                                Spacer()
                            }
                        }
                    }
                }
            }
            .navigationBarTitle("Browse")
            .navigationBarHidden(hideNavigationBar)
            .animation(.spring()) // for example
        }
    }
}

请注意,任何函数调用中的最后一个参数都可以放在一个闭包中。

所以...

                    .onTapGesture(count: 1, perform: {
                        self.hideNavigationBar.toggle()
                    })

可以成为...

                    .onTapGesture(count: 1) {
                        self.hideNavigationBar.toggle()
                    }

我个人认为语法更简单。

我认为,唯一的解决方案是在 SwiftUI 2 中使用位置函数

var body: some View {
    GeometryReader { geometry in
        NavigationView {
            ZStack {
                Color("background")
                    .ignoresSafeArea()
                
                // ContentView
            }
            .navigationBarTitleDisplayMode(.inline)
            .navigationBarItems(leading: logo, trailing: barButtonItems)
            .toolbar {
                ToolbarItem(placement: .principal) {
                    SearchBarButton(placeholder: LocalizedStringKey("home_vc.search_bar.placeholder"))
                        .opacity(isNavigationBarHidden ? 0 : 1)
                        .animation(.easeInOut(duration: data.duration))
                }
                
            }
        }
        .frame(height: geometry.size.height + (isNavigationBarHidden ? 70 : 0))
         // This is the key ⬇
        .position(x: geometry.size.width/2, y: geometry.size.height/2 - (isNavigationBarHidden ? 35 : 0))
        .animation(.easeInOut(duration: 0.38))
        .onTapGesture {
            isNavigationBarHidden.toggle()
        }
    }
}