Created
April 7, 2021 15:56
-
-
Save darrarski/22edfc682dc918f6f6cc5e441429c6cf to your computer and use it in GitHub Desktop.
Lazy navigation in SwiftUI - animations issue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Based on "Lazy navigation in SwiftUI" blogpost by Majid Jabrayilov | |
// Blogpost url: https://swiftwithmajid.com/2021/01/27/lazy-navigation-in-swiftui/ | |
// This gist shows an issue with using conditional NavigationLinks. | |
// When using StackNavigationViewStyle push animations are not present. | |
import SwiftUI | |
@main | |
struct LazyNavApp: App { | |
var body: some Scene { | |
WindowGroup { | |
NavigationView { | |
FirstView() | |
} | |
.navigationViewStyle(StackNavigationViewStyle()) // comment this line to fix missing animations when pushing views | |
} | |
} | |
} | |
// MARK: - First screen | |
struct FirstView: View { | |
@State var second: Second? | |
var body: some View { | |
ZStack { | |
Color.yellow.ignoresSafeArea() | |
Button(action: { second = Second() }) { | |
Text("Present Second") | |
} | |
} | |
.navigationTitle("First") | |
.navigate(using: $second, destination: SecondView.init(second:)) | |
} | |
} | |
// MARK: - Second screen | |
struct Second {} | |
struct SecondView: View { | |
var second: Second | |
@State var third: Third? | |
init(second: Second) { | |
self.second = second | |
} | |
var body: some View { | |
ZStack { | |
Color.green.ignoresSafeArea() | |
Button(action: { third = Third() }) { | |
Text("Present Third") | |
} | |
} | |
.navigationTitle("Second") | |
.navigate(using: $third, destination: ThirdView.init(third:)) | |
} | |
} | |
// MARK: - Third screen | |
struct Third {} | |
struct ThirdView: View { | |
var third: Third | |
var body: some View { | |
ZStack { | |
Color.gray.ignoresSafeArea() | |
Text("Third") | |
} | |
.navigationTitle("Third") | |
} | |
} | |
// MARK: - Navigation utils | |
extension NavigationLink where Label == EmptyView { | |
init?<Value>( | |
_ binding: Binding<Value?>, | |
@ViewBuilder destination: (Value) -> Destination | |
) { | |
guard let value = binding.wrappedValue else { | |
return nil | |
} | |
let isActive = Binding( | |
get: { true }, | |
set: { newValue in if !newValue { binding.wrappedValue = nil } } | |
) | |
self.init(destination: destination(value), isActive: isActive, label: EmptyView.init) | |
} | |
} | |
extension View { | |
@ViewBuilder | |
func navigate<Value, Destination: View>( | |
using binding: Binding<Value?>, | |
@ViewBuilder destination: (Value) -> Destination | |
) -> some View { | |
background(NavigationLink(binding, destination: destination)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment