Animation toolbarBackground visibility not works

32 Views Asked by At

I'm trying to set toolbarBackground visibile with animation, but it's happen immediatly. Are there ways to make this with animation?

struct MyView: View {
    @State private var barHidden = true
    
    var body: some View {
        NavigationStack {
            Button("action") {
                barHidden.toggle()
            }
            .animation(.easeInOut, value: barHidden)
            .toolbar {
                ToolbarItem(placement: .principal) {
                    Text("Title")
                }
            }
            .toolbarBackground(Color.red, for: .navigationBar)
            .toolbarBackground(barHidden ? .hidden : .visible, for: .navigationBar)
        }
    }
}

1

There are 1 best solutions below

0
MatBuompy On BEST ANSWER

All you need to do is take advantage of the safeAreaInsets modifier to simulate the animation of the toolbar background. Here's what I've done:

  1. Get the safeArea size using a GeomtryReader
  2. Apply the safeAreaInsets modifier to the NavigationStack to place a View where the toolbar is supposed to be, which, in this case, will be Rectangle
  3. Add an overlay to aforementioned Rectangle that will be our title

Here's the code:

struct MyView: View {
    @State private var barHidden = true
    
    var body: some View {
        GeometryReader { proxy in
            let safeArea = proxy.safeAreaInsets
            NavigationStack {
                Button("action") {
                    withAnimation(.easeInOut) {
                        barHidden.toggle()
                    }
                }
            }
            .safeAreaInset(edge: .top) {
                Rectangle()
                    .fill(barHidden ? .clear : .red)
                    .overlay(alignment: .center) {
                        Text("Title")
                            /// Placed exactly where the default Title appears when using the toolbar modifier
                            .padding(.top, safeArea.top / 2)
                    }
                    /// The red area I was seeing with your oringinal code was 2 times the safe area .top
                    .frame(height: safeArea.top * 2)
                    .ignoresSafeArea(.container, edges: .top)
            }
        }
    }
}

Here's the result:

Animated Toolbar Backgound