Hi all, I am hoping to advocate for allowing deep ...
# compose
l
Hi all, I am hoping to advocate for allowing deep links as start destinations within compose navigation. I saw this thread that discussed this a several months ago, but it doesn't seem to have reached the outcome I expected. I've raised a ticket to introduce this behaviour (https://issuetracker.google.com/issues/214733434), but it was marked as a duplicate of an issue with a similar explanation. I don't suppose anyone else would be interested in discussing this?
s
@Ian Lake as fyi
👍 1
l
I believe in this situation my usecase is valid. I am working on a project where I use two NavHosts for tablets/foldables. When a user clicks something on the right panel (for example an email), I want to be able to open a second NavHost and immediately set the start destination to this email. Without being able to support a deep link as a start destination, the only way I have managed to get this to work is to create an 'empty' composable, wait for the NavGraph to be ready, then trigger navigation to the deep link
i
I was the one who closed out the original issue and marked this one as an exact duplicate - that's not what a
startDestination
is or what it is used for
The
startDestination
is a
route
.
l
any suggestions for my usecase? I'm hoping to create a library to make navigation for foldables more seamless for developers. i.e. if they are on a phone the deep link would open in the same NavHost, and if they are on a foldable a new NavHost is opened in the right pane and it starts on the correct page
thanks for the speedy reply =D
my solution - using a blank composable and then deep linking works reasonably well, however there is a noticable white flicker due to the crossfade animation
i
That's not how you do two pane layouts. Did you get a chance to read the documentation on adaptive UIs and Navigation? https://developer.android.com/jetpack/compose/nav-adaptive
l
yes, I've read through the documentation. I'm hoping to provide a device agnostic approach that could make it appealing to developers to support tablets and foldables without explicitly coding for it
I'm hoping going to release an initial version of this approach in the next few weeks. I believe I have avoided the pitfalls discussed within https://developer.android.com/jetpack/compose/nav-adaptive#avoid-nav-as-side-effect
i
Explicitly choosing the most appropriate method (be it changing the presentation, amount of data shown, or doing something more extreme like having that specific destination implement a two pane layout) for making each destination responsive is a key part of the thought process; bypassing that is not the road you should consider long term viable
l
ah, but in my API I will be making it explicit.
i
Then the documentation is indeed the correct approach - the routes in your graph should cover the full area of the NavHost, even if an individual route is implemented differently (side by side vs overlapping) based on the device type
l
i.e. the user will explicitly say whether or not it should be shown in the left or right pane, and depending on the form factor it will either open a second pane, or open it in the first pane. Then if the user unfolds their foldable, the second pane appears as expected. i.e.
navigate(SECOND_PANE, "route")
i
So sure, having a
NavGraphBuilder.twoPaneComposable
helper method that sets up that one pane vs two pane approach is valid and useful
l
yeah. I'm really keen to see how useful it might be
I would even be happy to contribute it back in some manner if it has merit
I'll let keep you posted when it's available =]
You hit the nail on the head about overlapping NavHosts, that's indeed how I am doing it
i
but having a global idea of a left pane vs right pane is specifically not a pattern that we recommend - that's exactly what the Routes vs screens section is trying to get at - it is a per destination choice: https://developer.android.com/jetpack/compose/nav-adaptive#routes-vs-screens
As there are absolutely destinations (login, a full screen photo viewer, video playback) that are not two pane and should not be two pane on any device
l
The way that I am building this library would allow you to only have one pane on a foldable or tablet. It would be up to the developer how they want to use it
a
For the case of nested `NavHost`s, would splitting up the deep link be a solution? In other words, the outer
NavHost
picks up the first “half” of the deep link, and then defers the second “half” to the inner
NavHost
i
We actually specifically talk about deep linking over in the non-compose world for two pane layouts: https://developer.android.com/guide/topics/ui/layout/twopane?hl=en#navigation
The destinations in the detail pane's navigation graph should not be present in any outer, app-wide navigation graph. However, any deep links within the detail pane's navigation graph should be attached to the destination that hosts the 
SlidingPaneLayout
. This ensures that external deep links first navigate to the 
SlidingPaneLayout
 destination and then navigate to the correct detail pane destination.
If you really want an individual destination to have a stack of destinations in their embedded right pane, that's also automatically supported for actual deep links 🙂
l
Perhaps in this case I might be misusing the term deep link. In this case it's not a deep link from outside of the app, i just need to be able to support a dynamic route, and at the moment deep links are the only way to support that
i
That's not true at all
As per those issues, your
defaultValue
and even the whole
startDestination
are variables just like any other
l
Perhaps poor wording on my part? I was replying to @Alex Vanyo
i
I think you have all the tools you need right now between setting the
startDestination
to the route of your choice and using a
defaultValue
on an argument for that start destination, to have any kind of 'dynamic route' you think you need
l
Can the default argument be dynamic? I.e. if someone clicks an email, can my start destination be email/1 or email/2?
i
your
defaultValue
for the
emailId
can certainly change to whatever you want, whenever you want
again, as per the issue your issue was marked as a duplicate of
a
I think code might be easier?
Copy code
val startIndex = 1

NavHost(
    navController = navController,
    startDestination = "deeplink/record/{index}",
  ) {
    composable(
      route = "deeplink/record/{index}",
      arguments = listOf(navArgument("index") {
          type = NavType.IntType,
          defaultValue = startIndex
      }),
      content = { backStackEntry ->
        ...
      }
    )
}
l
Ah... I think I get it now. I just need to make sure that when I create the graph I set the default value dynamically. I suppose then this is not an issue for my library, but a documentation detail I will need to ensure others how attempt this follow
Yeah, exactly @Alex Vanyo. Thanks both!
👍 1
Sorry for taking so much of both of your time. I really appreciate it! I'll post back in this thread when I publish my 1.0.0 😅