SwiftUI:显示没有动画的全屏覆盖

SwiftUI: show fullScreenCover without animation

This amazing question 由于“缺乏技术细节”而关闭,所以我肯定会在这里放很多。

设置:

  1. 创建一个 iOS SwiftUI 应用程序
  2. 添加文件如下
  3. 观察问题

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

问题:

观看视频:应用程序启动后,可以看到“解锁视图”,并在短暂的动画延迟后出现“锁定屏幕”。

期望的结果:

应用程序在启动后立即显示“锁屏”,但可以通过按“解锁”按钮将其关闭。

Video of the problem

Project file with sample app

希望您觉得这很有用。我知道它没有 FullScreenCover,但这会立即显示它。

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

基于您对@AlexanderThoren 回答的评论。我添加了向下动画并简化了代码。

添加过渡动画。

添加此扩展以隐藏 - 显示视图。

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

并将其用于您的内容视图

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

编辑 :如评论中所述,这是没有视图扩展的解决方案。

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