nathantannar4 / Transmission

Bridges UIKit presentation APIs to a SwiftUI API so you can use presentation controllers, interactive transitions and more.
BSD 2-Clause "Simplified" License
378 stars 13 forks source link

Slide presentation gesture conflicts with UINavigationController back gesture #23

Closed PhilipDukhov closed 8 months ago

PhilipDukhov commented 8 months ago

The back gesture of the navigation controller is often not recognized because of the slide gesture. Here's some sample code:

struct ContentView: View {
    var body: some View {
        Text("Root")
            .presentation(
                transition: .slide(
                    options: .init(
                        edge: .bottom,
                        options: .init(
                            shouldAutomaticallyDismissDestination: false,
                            modalPresentationCapturesStatusBarAppearance: true
                        )
                    )
                ),
                isPresented: .constant(true)
            ) {
                NavigationContainer {
                    DestinationLink(destination: {
                        Color.gray
                            .frame(maxWidth: .infinity, maxHeight: .infinity)
                    }, label: { Color.brown })
                }
            }
    }
}

struct NavigationContainer<Content: View>: UIViewControllerRepresentable {
    @ViewBuilder let content: () -> Content

    func makeUIViewController(context: Context) -> UINavigationController {
        UINavigationController(rootViewController: UIHostingController(rootView: content()))
    }

    func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {
        (uiViewController.viewControllers.first as? UIHostingController<Content>)?.rootView = content()
    }
}

Interesting that unlike DestinationLink, NavigationLink works fine with this code - I wonder how it solves this corner case, and if it's something DestinationLink would want to do.

I was able to fix it locally by adding the following method to SlidePresentationController, maybe you'll find a cleaner fix.

func gestureRecognizer(
    _ gestureRecognizer: UIGestureRecognizer,
    shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer
) -> Bool {
    otherGestureRecognizer.isKind(of: UIScreenEdgePanGestureRecognizer.self)
}
nathantannar4 commented 8 months ago

Will be fixed in 1.1.0