@@ -18,14 +18,21 @@ package com.google.samples.apps.nowinandroid.ui.interests2pane
18
18
19
19
import androidx.activity.compose.BackHandler
20
20
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
21
+ import androidx.compose.material3.adaptive.layout.AnimatedPane
21
22
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffold
22
23
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole
23
24
import androidx.compose.material3.adaptive.layout.PaneAdaptedValue
25
+ import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem
24
26
import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator
25
27
import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator
26
28
import androidx.compose.runtime.Composable
27
- import androidx.compose.runtime.LaunchedEffect
28
29
import androidx.compose.runtime.getValue
30
+ import androidx.compose.runtime.key
31
+ import androidx.compose.runtime.mutableStateOf
32
+ import androidx.compose.runtime.remember
33
+ import androidx.compose.runtime.saveable.Saver
34
+ import androidx.compose.runtime.saveable.rememberSaveable
35
+ import androidx.compose.runtime.setValue
29
36
import androidx.hilt.navigation.compose.hiltViewModel
30
37
import androidx.lifecycle.compose.collectAsStateWithLifecycle
31
38
import androidx.navigation.NavGraphBuilder
@@ -39,8 +46,10 @@ import com.google.samples.apps.nowinandroid.feature.interests.navigation.INTERES
39
46
import com.google.samples.apps.nowinandroid.feature.interests.navigation.TOPIC_ID_ARG
40
47
import com.google.samples.apps.nowinandroid.feature.topic.TopicDetailPlaceholder
41
48
import com.google.samples.apps.nowinandroid.feature.topic.navigation.TOPIC_ROUTE
49
+ import com.google.samples.apps.nowinandroid.feature.topic.navigation.createTopicRoute
42
50
import com.google.samples.apps.nowinandroid.feature.topic.navigation.navigateToTopic
43
51
import com.google.samples.apps.nowinandroid.feature.topic.navigation.topicScreen
52
+ import java.util.UUID
44
53
45
54
private const val DETAIL_PANE_NAVHOST_ROUTE = " detail_pane_route"
46
55
@@ -76,17 +85,42 @@ internal fun InterestsListDetailScreen(
76
85
selectedTopicId : String? ,
77
86
onTopicClick : (String ) -> Unit ,
78
87
) {
79
- val listDetailNavigator = rememberListDetailPaneScaffoldNavigator()
88
+ val listDetailNavigator = rememberListDetailPaneScaffoldNavigator(
89
+ initialDestinationHistory = listOfNotNull(
90
+ ThreePaneScaffoldDestinationItem (ListDetailPaneScaffoldRole .List ),
91
+ ThreePaneScaffoldDestinationItem <Nothing >(ListDetailPaneScaffoldRole .Detail ).takeIf {
92
+ selectedTopicId != null
93
+ },
94
+ ),
95
+ )
80
96
BackHandler (listDetailNavigator.canNavigateBack()) {
81
97
listDetailNavigator.navigateBack()
82
98
}
83
99
84
- val nestedNavController = rememberNavController()
100
+ var nestedNavHostStartDestination by remember {
101
+ mutableStateOf(selectedTopicId?.let (::createTopicRoute) ? : TOPIC_ROUTE )
102
+ }
103
+ var nestedNavKey by rememberSaveable(
104
+ stateSaver = Saver ({ it.toString() }, UUID ::fromString),
105
+ ) {
106
+ mutableStateOf(UUID .randomUUID())
107
+ }
108
+ val nestedNavController = key(nestedNavKey) {
109
+ rememberNavController()
110
+ }
85
111
86
112
fun onTopicClickShowDetailPane (topicId : String ) {
87
113
onTopicClick(topicId)
88
- nestedNavController.navigateToTopic(topicId) {
89
- popUpTo(DETAIL_PANE_NAVHOST_ROUTE )
114
+ if (listDetailNavigator.isDetailPaneVisible()) {
115
+ // If the detail pane was visible, then use the nestedNavController navigate call
116
+ // directly
117
+ nestedNavController.navigateToTopic(topicId) {
118
+ popUpTo(DETAIL_PANE_NAVHOST_ROUTE )
119
+ }
120
+ } else {
121
+ // Otherwise, recreate the NavHost entirely, and start at the new destination
122
+ nestedNavHostStartDestination = createTopicRoute(topicId)
123
+ nestedNavKey = UUID .randomUUID()
90
124
}
91
125
listDetailNavigator.navigateTo(ListDetailPaneScaffoldRole .Detail )
92
126
}
@@ -95,34 +129,34 @@ internal fun InterestsListDetailScreen(
95
129
value = listDetailNavigator.scaffoldValue,
96
130
directive = listDetailNavigator.scaffoldDirective,
97
131
listPane = {
98
- InterestsRoute (
99
- onTopicClick = ::onTopicClickShowDetailPane,
100
- highlightSelectedTopic = listDetailNavigator.isDetailPaneVisible(),
101
- )
102
- },
103
- detailPane = {
104
- NavHost (
105
- navController = nestedNavController,
106
- startDestination = TOPIC_ROUTE ,
107
- route = DETAIL_PANE_NAVHOST_ROUTE ,
108
- ) {
109
- topicScreen(
110
- showBackButton = ! listDetailNavigator.isListPaneVisible(),
111
- onBackClick = listDetailNavigator::navigateBack,
132
+ AnimatedPane {
133
+ InterestsRoute (
112
134
onTopicClick = ::onTopicClickShowDetailPane,
135
+ highlightSelectedTopic = listDetailNavigator.isDetailPaneVisible(),
113
136
)
114
- composable(route = TOPIC_ROUTE ) {
115
- TopicDetailPlaceholder ()
137
+ }
138
+ },
139
+ detailPane = {
140
+ AnimatedPane {
141
+ key(nestedNavKey) {
142
+ NavHost (
143
+ navController = nestedNavController,
144
+ startDestination = nestedNavHostStartDestination,
145
+ route = DETAIL_PANE_NAVHOST_ROUTE ,
146
+ ) {
147
+ topicScreen(
148
+ showBackButton = ! listDetailNavigator.isListPaneVisible(),
149
+ onBackClick = listDetailNavigator::navigateBack,
150
+ onTopicClick = ::onTopicClickShowDetailPane,
151
+ )
152
+ composable(route = TOPIC_ROUTE ) {
153
+ TopicDetailPlaceholder ()
154
+ }
155
+ }
116
156
}
117
157
}
118
158
},
119
159
)
120
- LaunchedEffect (Unit ) {
121
- if (selectedTopicId != null ) {
122
- // Initial topic ID was provided when navigating to Interests, so show its details.
123
- onTopicClickShowDetailPane(selectedTopicId)
124
- }
125
- }
126
160
}
127
161
128
162
@OptIn(ExperimentalMaterial3AdaptiveApi ::class )
0 commit comments