Lukas Anda
07/04/2024, 11:13 AMLukas Anda
07/04/2024, 11:15 AMclass CustomViewController: UIViewController {
var backGestureProvider : BackGestureProvider?
override func viewDidLoad() {
super.viewDidLoad()
// Initialize the edge pan gesture recognizer
let edgePanGestureRecognizer = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(handleEdgePan(_:)))
edgePanGestureRecognizer.edges = .left // Set the edge to left
// Add the gesture recognizer to the view
self.view.addGestureRecognizer(edgePanGestureRecognizer)
// Add the nested view controller
addNestedViewController()
}
@objc func handleEdgePan(_ gestureRecognizer: UIScreenEdgePanGestureRecognizer) {
let translation = gestureRecognizer.translation(in: view)
switch gestureRecognizer.state {
case .began:
// Gesture began, start tracking
print("Gesture began")
case .changed:
// Gesture changed, update tracking
let progress = translation.x / view.bounds.width
print("Gesture changed, progress: \(progress)")
// You can update the UI based on progress if needed
case .ended:
// Gesture ended, determine whether to complete the navigation or not
let velocity = gestureRecognizer.velocity(in: view)
if translation.x > view.bounds.width / 2 || velocity.x > 1000 {
// Complete the navigation
print("Gesture ended, completing navigation")
backGestureProvider?.onSwipeBack()
} else {
// Cancel the navigation
print("Gesture ended, cancelling navigation")
// Optionally, add logic to animate the UI back to the original state
}
case .cancelled, .failed:
// Gesture cancelled or failed, reset the UI
print("Gesture cancelled or failed")
default:
break
}
}
func addNestedViewController() {
let nestedViewController = MainKt.MainViewController(backGestureProvider: provideSwipeBack(_:))
// Add the nested view controller as a child
addChild(nestedViewController)
// Add the nested view controller's view to the view hierarchy
view.addSubview(nestedViewController.view)
// Set up constraints or frame for the nested view
nestedViewController.view.frame = view.bounds
nestedViewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
// Notify the nested view controller that it has been moved to a parent
nestedViewController.didMove(toParent: self)
}
func provideSwipeBack(_ provider: BackGestureProvider) -> Void {
backGestureProvider = provider
}
}
Lukas Anda
07/04/2024, 11:17 AMMainKt.MainViewController
contains the backGestureProvider. This is an interface that is implemented on Kotlin side which just passes a reference to a function Swift side can call (look for backGestureProvider?.onSwipeBack()
in step 1. Right now it's set up to only trigger on swipe completion but can be modified to actually provide the percentage (check the comments in the code)Lukas Anda
07/04/2024, 11:18 AMfun MainViewController(backGestureProvider: (BackGestureProvider) -> Unit): UIViewController = ComposeUIViewController() {
App(backGestureProvider)
}
Lukas Anda
07/04/2024, 11:20 AMApp
function (which is the actual compose root), send it to the appropriate NavHost
where you can do something like this (I have created a wrapper for it called AppNavigation):
@Composable
fun AppNavigation(backGestureProvider: (BackGestureProvider) -> Unit, modifier: Modifier = Modifier, navController: NavHostController = rememberNavController()) {
LaunchedEffect(Unit) {
backGestureProvider(object : BackGestureProvider {
override fun onSwipeBack() {
navController.navigateUp()
}
})
}
}
Lukas Anda
07/04/2024, 11:22 AMPau Marzo
07/04/2024, 11:47 AMLukas Anda
07/04/2024, 11:49 AMStylianos Gakis
07/04/2024, 11:54 AMnavController.navigateUp()
when you do the back gesture, but popBackstack
instead for normal back gestures.Lukas Anda
07/04/2024, 11:55 AMIvan Matkov
07/08/2024, 8:20 AMLukas Anda
07/08/2024, 8:24 AMMarcello Galhardo
07/09/2024, 5:24 PMLukas Anda
07/11/2024, 8:26 AM