Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tapping the toggle button animates the offset

The glaringly obvious problem is that this just uses an arbitrary value for the animated offset, and this quickly breaks when considering dynamic type

the animated offset is less than the height of the view

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

like image 737
XmasRights Avatar asked Sep 03 '25 03:09

XmasRights


1 Answers

It can be done just with transition, like

demo

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()
    }
}
like image 124
Asperi Avatar answered Sep 04 '25 20:09

Asperi