4

I have a custom alert that I'm trying to slide down from the top of the screen on presentation. I'm using transition and the new .animation modifier for iOS 15:

import SwiftUI

struct SlideOverAlert: View {
    var text: String
    @Binding var isPresented: Bool
    var dismissAction: () -> Void
    
    var body: some View {
        if isPresented {
            ZStack {
                Rectangle()
                    .edgesIgnoringSafeArea(.top)
                    .frame(height: 80)
                    .foregroundColor(.orange)
                HStack {
                    Text(text)
                    Spacer()
                    Button(action: dismissAction) {
                        Image(systemName: "xmark")
                    }
                }
                .foregroundColor(.white)
                .padding()
            }
            .transition(.move(edge: isPresented ? .top : .bottom))
            .animation(.default, value: isPresented)
        }
    }
}

The code I have isn't working. And I can't figure out why...

Here's my preview code:

struct SlideOverAlert_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
    
    struct ContentView: View {
        @State var alertIsPresented = true
        
        var body: some View {
            GeometryReader { _ in
                ZStack(alignment: .top) {
                    VStack {
                        Spacer()
                        Button(action: { alertIsPresented.toggle() }) {
                            Text("Toggle")
                        }
                        Spacer()
                    }
                    SlideOverAlert(
                        text: "That isn't going to work",
                        isPresented: $alertIsPresented
                    ) {
                        alertIsPresented.toggle()
                    }
                }
            }
        }
    }
}
emehex
  • 9,874
  • 10
  • 54
  • 100
  • Try to set animation like this ```.animation(.default) .transition(.asymmetric(insertion: .move(edge: .bottom), removal: .move(edge: .top)))``` – Raja Kishan Jul 13 '21 at 14:58
  • 2
    .animation(.default) without `value:` is deprecated, see: https://www.hackingwithswift.com/articles/235/whats-new-in-swiftui-for-ios-15 – emehex Jul 13 '21 at 15:03

1 Answers1

0

If you are trying to build a custom Alert, I would recommend using the new fullScreenCover (IOS 14+). In your previews / content views, it'll look something like this:

// Attach the custom Alert to the view, bound to our state variable
.fullScreenCover(isPresented: $alertIsPresented) {
     SlideOverAlert()
}

This way, you do not need to pass a state variable into SliderOverAlert, and in SlideOverAlert you'll then be able to call dismiss() on the @Environment presentation mode's wrapped value to dismiss the view. It's much cleaner. If you need to keep the background clear, see this answer. This said, these suggestions do not produce the slide down effect you are looking for. If you're dead set on that effect, I might suggest one of the following. Transitions don't seem like the best solution here. A. Use a MatchedGeometryEffect to animate between the two different variations of the view you are trying to display. If you're trying to have everything animate smoothly including your buttons, this might be preferable, as MatchedGeometryEffect maintains proportional spacing between the transformed views. B. Keep your code as is, but remove your if statement and replace your .transition( line with something like this: .offset(x: 0, y: isPresented ? 0 : -1000). Ideally though, use a GeometryReader to determine your offset rather than a raw value like 1000. This should cause your view to programmatically animate in and out at the expense of the view always being there, even if it's out of sight. Unlike A., though, the view will remain static throughout this animation.

Vera Gonzalez
  • 578
  • 2
  • 9
  • Thanks, but I'm not looking for a fullscreen... Just something small (notice frame = `height: 80`) that can be tapped away – emehex Jul 13 '21 at 18:23