Home > Blockchain >  SwiftUI: show fullScreenCover without animation
SwiftUI: show fullScreenCover without animation

Time:11-26

This amazing question got closed due to "lack of technical details", so I'm sure to put a plenty of here.

Setup:

  1. Create an iOS SwiftUI app
  2. Add files as follows
  3. Observe the problem

AppleApp.swift

import SwiftUI

@main
struct AppleApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

ContentView.swift

import SwiftUI

struct ContentView: View {
    @State var isLocked = true

    var body: some View {
        VStack {
            Text("Unlocked view")
                .padding()
        }.fullScreenCover(isPresented: $isLocked) {

        } content: {
            LockScreen($isLocked)
        }


    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

LockScreen.swift

import SwiftUI

struct LockScreen: View {
    @Binding var isLocked: Bool

    init(_ isLocked: Binding<Bool>) {
        self._isLocked = isLocked
    }

    var body: some View {
        ZStack {
            Color.gray
            VStack {
                Text("Locked")
                Button("Unlock") {
                    print("unlock button pressed")
                    isLocked = false
                }
            }
        }
    }
}

struct LockScreen_Previews: PreviewProvider {
    @State static var isLocked: Bool = true
    static var previews: some View {
        LockScreen($isLocked)
    }
}

The problem:

Take a look at the video: after the app launches the "unlocked view" is visible and "LockScreen" appears after a short delay with animation.

Desired outcome:

The app shows "LockScreen" just after the launch, but it's possible to dismiss it by pressing the "unlock" button.

Video of the problem

Project file with sample app

CodePudding user response:

Hope you find this useful. I know it doesn't have a FullScreenCover, but this will show it instantly.

import SwiftUI

struct ContentView: View {
    @State var isLocked = true
    
    var body: some View {
        if self.isLocked {
            LockScreen(isLocked: self.$isLocked)
        } else {
            VStack {
                Text("Unlocked view")
                    .padding()
            }
        }
    }
}

struct LockScreen: View {
    @Binding var isLocked: Bool
    
    var body: some View {
        ZStack {
            Color.gray
            VStack {
                Text("Locked")
                Button("Unlock") {
                    print("unlock button pressed")
                    isLocked = false
                }
            }
        }
        .ignoresSafeArea()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

CodePudding user response:

Based on your comment on the @AlexanderThoren answere. I added down animation and also simplify the code.

Add a transition animation.

Add this extension to hide - show view.

extension View {
    func showLockView(isLocked: Binding<Bool>) -> some View {
        ZStack {
            self
            if isLocked.wrappedValue {
                LockScreen(isLocked: isLocked).animation(.default).transition(AnyTransition.move(edge: .bottom))
            }
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
    }
}

And use it with your content view

struct ContentView: View {
    @State var isLocked = true
    
    var body: some View {
        VStack {
            Text("Unlocked view")
                .padding()
        }
        .showLockView(isLocked: $isLocked) // << Here
    }
}

Edit : As mentioned in the comment, here is the solution without View extension.

struct ContentView: View {
    @State var isLocked = true
    
    var body: some View {
        ZStack {
            VStack {
                Text("Unlocked view")
                    .padding()
            }
            if isLocked {
                LockScreen(isLocked: $isLocked)
                    .edgesIgnoringSafeArea(.all)
                    .animation(.default)
                    .transition(AnyTransition.move(edge: .bottom))
            }
        }
    }
}
  • Related