This amazing question got closed due to "lack of technical details", so I'm sure to put a plenty of here.
Setup:
- Create an iOS SwiftUI app
- Add files as follows
- 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.
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))
}
}
}
}