3

In UIKit-based application we can have custom navigation transitions using UIViewControllerAnimatedTransitioning protocol.

Is there an equivalent in SwiftUI?

I know we can already animate between removing and adding views. But how do we do this when we push and pop to the navigation stack?

Asperi
  • 228,894
  • 20
  • 464
  • 690
swift nub
  • 2,747
  • 3
  • 17
  • 39
  • Standard `NavigationView` does not allow customisation for transitions for now. You can use/create custom navigation instead. Consider for example this solution https://stackoverflow.com/a/59087574/12299030 – Asperi Aug 20 '20 at 04:33
  • @Asperi That’s a terrible suggestion. This basically breaks any accessibility support built into UINavigationController, as well all the built-in tools provided. Just like it’s terrible when web “apps” do this, it’s equally terrible with SwiftUI. – Léo Natan Aug 21 '20 at 22:14
  • The correct solution is to either wrap UINavigationController manually, or otherwise obtain a reference to it, which is rather simple. – Léo Natan Aug 21 '20 at 22:15

1 Answers1

3

There isn't anything like this available in SwiftUI's APIs so far afaik. Make sure to open an enhancement request with Apple.

Implementing "navigation" on your own is a terrible idea, as you basically give all the accessibility and facility support afforded by UINavigationController.

Instead, here is a suggestion:

Either by means of a custom SwiftUI view or modifier, wrap the NavigationView with a UIViewControllerRepresentable wrapper, which in turn sets up a UIHostingController subclass, which waits for addChild(_:) to be called, which will be the navigation controller added as a child of the hosting controller. From here, if your animations are "static" (e.g. do not require any subview to subview transition), you can accomplish this here by implementing the navigation controller delegate, and providing the animation controller.

If you do need more evolved transitions (such as Photos.app's photo transition), you can create a custom UIViewRepresentable wrapper, which will serve as markers for "from" views and "to" views, you can then use those discover in UIKit, and e.g. can snapshot and animate in transitions.

Proposed API can look like this:

struct ContentView1: View {
    var body: some View {
        NavigationLink(destination: DetailView()) {
            Image("small").customSourceTarget()
        }.navigationBarTitle("Navigation")  
    }
}

struct ContentView2: View {
    var body: some View {
        Image("large").customTransitionTarget()
    }
}

NavigationView {
    ContentView1()
}.customAnimatable()
Léo Natan
  • 56,823
  • 9
  • 150
  • 195