SwiftUI offset animation problem while in preparing bottomsheet

Viewed 249

I wanted to make a bottomsheet in SwiftUI with my own efforts, I open it using animation, but my animation doesn't work when closing, what is the reason? I wonder if the offset value is increasing with animation, is there a problem while it is decreasing I am not very good at SwiftUI so I could not fully understand the problem.

    struct ContentView: View {
    @State var isOpen = false
    @State var offset =  UIScreen.main.bounds.height / 3
    
    var body: some View {
        ZStack {
            Color.blue
                .ignoresSafeArea()
            
            Button(action: {
                self.isOpen.toggle()
            }, label: {
                ZStack {
                    RoundedRectangle(cornerRadius: 25.0)
                        .foregroundColor(.black)
                    
                    Text("Open")
                        .font(.title2)
                        .fontWeight(.bold)
                        .foregroundColor(.white)
                }
            })
            .buttonStyle(DefaultButtonStyle())
            .frame(width: 300, height: 50, alignment: .center)
            
            if isOpen {
                GeometryReader { geometry in
                    VStack {
                        Spacer()
                        BottomSheet()
                            .frame(width: geometry.size.width,
                                   height: geometry.size.height / 3,
                                   alignment: .center)
                            .background(
                                Color.white
                            )
                            .offset(y: offset)
                            .onAppear(perform: {
                                withAnimation {
                                    self.offset = 0
                                }
                            })
                            .onDisappear(perform: {
                                withAnimation {
                                    self.offset = UIScreen.main.bounds.height / 3
                                }
                            })

                    }.ignoresSafeArea()

                }
            }
        }
    }
}

BottomSheet

  struct BottomSheet: View {
    var body: some View {
        Text("Hello, World!")
    }
}
1 Answers

onDisappear gets called when the view was removed, that's the reason custom animation not working :

struct ContentView: View {
    @State var isOpen = false
    
    var offset: CGFloat {
        isOpen ? 0 : UIScreen.main.bounds.height / 3
    }
    
    var body: some View {
        ZStack {
            Color.blue
                .ignoresSafeArea()
            
            Button(action: {
                self.isOpen.toggle()
            }, label: {
                ZStack {
                    RoundedRectangle(cornerRadius: 25.0)
                        .foregroundColor(.black)
                    
                    Text("Open")
                        .font(.title2)
                        .fontWeight(.bold)
                        .foregroundColor(.white)
                }
            })
            .buttonStyle(DefaultButtonStyle())
            .frame(width: 300, height: 50, alignment: .center)
            
            GeometryReader { geometry in
                VStack {
                    Spacer()
                    BottomSheet()
                        .frame(width:geometry.size.width,
                               height: geometry.size.height / 3,
                               alignment: .center)
                        .background(
                            Color.white
                        )
                        .offset(y: offset)
                        .animation(.easeInOut(duration: 0.5))                            .transition(.move(edge: .bottom))
                }                            .edgesIgnoringSafeArea(.bottom)
            }
        }
    }
}
Related