compose-multiplatform icon indicating copy to clipboard operation
compose-multiplatform copied to clipboard

[UIKit] API for navigation between Compose screens

Open alexzhirkevich opened this issue 2 years ago • 5 comments

Short description: Provide API for native like(or really native) navigation between Compose screens on iOS with native gestures.

Previous title: [UIKit] Unclear behaviour of nested UIViewControllers lifecycle

I try to implement something like native uikit navigation for compose using UINavigationController and UiKitView. And i faced the moment when i need to be notified when controller is popped. I cannot override viewDidDissapear of UIViewController cause ComposeWindow is internal, so i tried to use DisposableEffect for that. But when ComposeWindow pops from UINavigationController, DisposableEffect inside composable block does never execute onDispose.

May be it is not a bug, i am not sure. Is there a way to be notified when nested UIViewController is disappeared?

Affected platforms Select one of the platforms below:

  • iOS

Versions

  • Kotlin version*: 1.8.20
  • Compose Multiplatform version*: 1.4.0

Expected behavior

onDispose called when controller is popped (or viewDidDisappear of ComposeWindow called)

To Reproduce

fun MainViewController() = ComposeUIViewController {

    val navController = remember {
        UINavigationController(ComposeUIViewController {}).apply {
            pushViewController(
                viewController = ComposeUIViewController {
                    Box(Modifier.fillMaxSize()) {
                        Text(
                            text = "Close me",
                            modifier = Modifier.align(Alignment.Center)
                        )
                    }
                    DisposableEffect(0) {
                        println("HELLO THERE")
                        onDispose {
                            println("THIS WOULD NEVER HAPPEN")
                        }
                    }
                },
                animated = true
            )
        }
    }

    UIKitView(
        modifier = Modifier.fillMaxSize(),
        factory = {
            navController.view
        }
    )
}

alexzhirkevich avatar Apr 12 '23 17:04 alexzhirkevich

Thanks! Your current goal is to have native iOS navigation with UINavigationController? Do you want to navigate betwee UIKit and Compose screens, or just navigate between different Compose screens?

I think it's completed to use this code:

 UIKitView(
        modifier = Modifier.fillMaxSize(),
        factory = {
            navController.view
        }
    )

This UIKitView looks redundant.

Maybe we can provide a better API for navigation between Compose screens and between UIKit screen and Compose.

dima-avdeev-jb avatar Apr 12 '23 17:04 dima-avdeev-jb

I want to navigate between different compose screens in a native way with swipe gestures and so on. It works and looks perfect btw, but i also want to be notified, when controller is popped from the screen.

alexzhirkevich avatar Apr 12 '23 17:04 alexzhirkevich

Ok, thanks! For now we have different goals for better performance and fixing other bugs in Compose, but this issue is important as well. We will provide the needful API in the future.

dima-avdeev-jb avatar Apr 12 '23 18:04 dima-avdeev-jb

Just a little example of what can be done for now with UINavigationController. It is awesome, isn't it?

https://user-images.githubusercontent.com/63979218/231277302-1a7972d4-42bc-4dab-9b6a-8d041db811bf.mp4

alexzhirkevich avatar Apr 12 '23 18:04 alexzhirkevich

Cool!

dima-avdeev-jb avatar Apr 12 '23 18:04 dima-avdeev-jb

@alexzhirkevich the plan is to release it as PR in Precompose lib?

matteocrippa avatar Apr 24 '23 11:04 matteocrippa

@matteocrippa

Multiplatform swipe back navigation was already added to precompose (https://github.com/Tlaster/PreCompose/issues/35). Looks almost the same as native. True native have some limitations and bugs now.

alexzhirkevich avatar Apr 24 '23 15:04 alexzhirkevich

I'm currently experimenting with a way to abstract navigation for all Compose targets in my project. Right now navigation on iOS or Desktop looks the same as on Android - screens are changed with crossfade animation. For now there is no back gesture on iOS (like on Android) but I might consider adding one.

lukwol avatar Apr 28 '23 12:04 lukwol

Original issue is related to #3201

alexzhirkevich avatar Jun 06 '23 11:06 alexzhirkevich

Just FYI, Decompose supports the predictive back gesture on all platforms. There is one known bug which I will fix soon, though. https://arkivanov.github.io/Decompose/extensions/compose/#predictive-back-gesture

Plus, there are feature requests to make it better customizable, so it could look closer to the native variant.

arkivanov avatar Jun 06 '23 12:06 arkivanov

Any updates on this? As awesome as the community libraries addressing this are, I think Compose Multiplatform needs first party navigation and resource management solutions as those are parts of the app that can't be migrated easily if a library gets abandoned or isn't quick enough to fix critical bugs or update to newer kotlin/compose releases.

AhmedMourad0 avatar Oct 05 '23 02:10 AhmedMourad0

@AhmedMourad0 Thanks! Yeah - you are right! We have resources library and want to enhance it. Code samples https://github.com/JetBrains/compose-multiplatform/blob/master/components/resources/demo/shared/src/commonMain/kotlin/org/jetbrains/compose/resources/demo/shared/UseResources.kt

Also we are looking at navigation as well! For now we are investigating different approaches and trying to find the best direction!

dima-avdeev-jb avatar Oct 05 '23 02:10 dima-avdeev-jb

Great news. I'm looking forward to first party solutions for navigation and resource management. In the meantime I've updated my navigation library to benefit from custom transitions and finally published it on Maven Central. As for the string resources on mobile, Android XMLs and iOS Strings Catalog, hidden behind common API works fine for me.

lukwol avatar Oct 06 '23 13:10 lukwol

For navigation inside compose we have ported jetpack compose navigation - see https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-navigation-routing.html If you need navigate between native screens and compose - use native/platform solution.

Supporting back gesture is tracked here - https://github.com/JetBrains/compose-multiplatform/issues/4419

MatkovIvan avatar Jun 07 '24 15:06 MatkovIvan

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.

okushnikov avatar Jul 14 '24 14:07 okushnikov

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.

okushnikov avatar Jul 14 '24 14:07 okushnikov

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.

okushnikov avatar Jul 14 '24 14:07 okushnikov