frzi / swiftui-router

Path-based routing in SwiftUI
MIT License
900 stars 43 forks source link

Make current stack index info public #56

Closed PhilipDukhov closed 2 years ago

PhilipDukhov commented 2 years ago

I'm trying to replicate system navigation behaviour: instead of offsetting the view on the whole width, they only offset 0.3 part of width.

How NavigationView+NavigationLink animation looks like:

To replicate it I've created the following transition:

let transitionDuration: Double = 2
let screenWidth = UIScreen.main.bounds.width
let hidingScreenWidth = UIScreen.main.bounds.width * 0.3

private func transition(for direction: NavigationAction.Direction?) -> AnyTransition {
    if direction == .deeper || direction == .sideways {
        return AnyTransition.asymmetric(insertion: .offset(x: screenWidth), removal: .offset(x: -hidingScreenWidth))
    } else {
        return AnyTransition.asymmetric(insertion: .offset(x: -hidingScreenWidth), removal: .offset(x: screenWidth))
    }
}

The problem is that the disappearing view is always on top - it looks as expected during pop, but not during push:

The solution is to apply zIndex depending on the route index in the back stack - the pushing view must have a higher zIndex than the current one.

SwitchRoutes {
    Group {
        Route("home") {
            ZStack {
                Color.white
                Button {
                    navigator.goBack()
                } label: {
                    Text("Back")
                }
            }
        }
        Route("init") {
            ZStack {
                HStack(spacing: 0) {
                    Color.gray.frame(width: UIScreen.main.bounds.width * 0.3)
                    Color.yellow.frame(maxWidth: .infinity)
                }
                NavLink(to: "/home") {
                    Text("Go next")
                }
            }
        }
        Route {
            Navigate(to: "init")
        }
    }.zIndex(Double(navigator.currentStackIndex))
}.navigationTransition()

To do this, I need to have information about the current route index, which is what this PR adds.

frzi commented 2 years ago

Hm! Incredible stuff you're showing! 😄

It's clear publicizing the current index is a useful addition. Because it's small and non-breaking I'll merge the pull request and release a patch version.

That said, keep in mind that this property may be deprecated in the future and be replaced with something akin to a .historyStackSize and .forwardStackSize 😉