'SwiftUI: Animate offset to slide in from off screen
I'm trying to animate in a view the bottom of its parent view. This is relatively easy to do by animating the offset, like so:
struct ContentView: View {
    @State var isShowingBanner = true
    var bannerOffset: CGFloat {
        isShowingBanner ? 0 : 60
    }
    var body: some View {
        VStack {
            VStack {
                Spacer()
                BannerView()
                    .offset(y: bannerOffset)
            }
            .border(Color.black, width: 1.0)
            .clipped()
            Spacer()
            Button("Toggle Banner") {
                withAnimation {
                    isShowingBanner.toggle()
                }
            }
        }
        .padding()
    }
}
The glaringly obvious problem is that this just uses an arbitrary value for the animated offset, and this quickly breaks when considering dynamic type
My question is:
Is there a way to properly determine the height of BannerView to correctly adjust this animation. Or is there a better way to achieve this effect?
Thanks all
Solution 1:[1]
It can be done just with transition, like
Tested with Xcode 13.3 / iOS 15.4
struct ContentView: View {
    @State var isShowingBanner = true
    var body: some View {
        VStack {
            VStack {
                Spacer()
                if isShowingBanner {
                    BannerView()
                        .transition(.move(edge: .bottom))  // << here !!
                }
            }
// >> empty container should not shrink !!
            .frame(maxWidth: .infinity, maxHeight: .infinity) 
            .border(Color.black, width: 1.0)
            .clipped()
            Spacer()
            Button("Toggle Banner") {
                withAnimation {
                    isShowingBanner.toggle()
                }
            }
        }
        .padding()
    }
}
    					Solution 2:[2]
If you want to determine the Height of the BannerView() You can use GeometryReader. I have created BannerView() Just for example bellow : -
   struct BannerView() : View {
        @Binding var height : CGFloat
        var body: some View {
            VStack{
               GeometryReader { proxy in
                  Rectangle().fill(.green).onAppear {
                      height = proxy.size.height
                  }
               }
            }.frame(height : 100)
        }
   }
So, the Binding value will provide height of the bannerView to your MainView(). You can use that to determine your offset.
   @State var isShowingBanner = true
   @State var offsetHeight : CGFloat = 0        
    var body: some View {
        VStack {
            VStack {
                Spacer()
                BannerView(height: $offsetHeight)
                    .offset(y: isShowingBanner ? 0 : offsetHeight)
            }
            .border(Color.black, width: 1.0)
            .clipped()
            Spacer()
            Button("Toggle Banner") {
                withAnimation {
                    isShowingBanner.toggle()
                }
            }
        }
        .padding()
    }
Hope you found this useful.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | Asperi | 
| Solution 2 | Namra Parmar | 



