Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add workaround for AnimatedPane by delaying navigation #1387

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 9 additions & 9 deletions app/dependencies/prodReleaseRuntimeClasspath.txt
Expand Up @@ -17,10 +17,10 @@ androidx.compose.animation:animation-android:1.7.0-alpha06
androidx.compose.animation:animation-core-android:1.7.0-alpha06
androidx.compose.animation:animation-core:1.7.0-alpha06
androidx.compose.animation:animation:1.7.0-alpha06
androidx.compose.foundation:foundation-android:1.6.3
androidx.compose.foundation:foundation-layout-android:1.6.3
androidx.compose.foundation:foundation-layout:1.6.3
androidx.compose.foundation:foundation:1.6.3
androidx.compose.foundation:foundation-android:1.7.0-alpha06
androidx.compose.foundation:foundation-layout-android:1.7.0-alpha06
androidx.compose.foundation:foundation-layout:1.7.0-alpha06
androidx.compose.foundation:foundation:1.7.0-alpha06
androidx.compose.material3.adaptive:adaptive-android:1.0.0-alpha10
androidx.compose.material3.adaptive:adaptive-layout-android:1.0.0-alpha10
androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha10
Expand Down Expand Up @@ -103,11 +103,11 @@ androidx.lifecycle:lifecycle-viewmodel:2.8.0-alpha04
androidx.loader:loader:1.0.0
androidx.localbroadcastmanager:localbroadcastmanager:1.0.0
androidx.metrics:metrics-performance:1.0.0-alpha04
androidx.navigation:navigation-common-ktx:2.7.4
androidx.navigation:navigation-common:2.7.4
androidx.navigation:navigation-compose:2.7.4
androidx.navigation:navigation-runtime-ktx:2.7.4
androidx.navigation:navigation-runtime:2.7.4
androidx.navigation:navigation-common-ktx:2.8.0-alpha06
androidx.navigation:navigation-common:2.8.0-alpha06
androidx.navigation:navigation-compose:2.8.0-alpha06
androidx.navigation:navigation-runtime-ktx:2.8.0-alpha06
androidx.navigation:navigation-runtime:2.8.0-alpha06
androidx.print:print:1.0.0
androidx.privacysandbox.ads:ads-adservices-java:1.0.0-beta05
androidx.privacysandbox.ads:ads-adservices:1.0.0-beta05
Expand Down
Expand Up @@ -27,7 +27,8 @@ import javax.inject.Inject
class Interests2PaneViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle,
) : ViewModel() {
val selectedTopicId: StateFlow<String?> = savedStateHandle.getStateFlow(TOPIC_ID_ARG, null)
val selectedTopicId: StateFlow<String?> =
savedStateHandle.getStateFlow(TOPIC_ID_ARG, savedStateHandle[TOPIC_ID_ARG])

fun onTopicClick(topicId: String?) {
savedStateHandle[TOPIC_ID_ARG] = topicId
Expand Down
Expand Up @@ -18,14 +18,20 @@ package com.google.samples.apps.nowinandroid.ui.interests2pane

import androidx.activity.compose.BackHandler
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
import androidx.compose.material3.adaptive.layout.AnimatedPane
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffold
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole
import androidx.compose.material3.adaptive.layout.PaneAdaptedValue
import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem
import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator
import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavGraphBuilder
Expand Down Expand Up @@ -76,17 +82,35 @@ internal fun InterestsListDetailScreen(
selectedTopicId: String?,
onTopicClick: (String) -> Unit,
) {
val listDetailNavigator = rememberListDetailPaneScaffoldNavigator()
val listDetailNavigator = rememberListDetailPaneScaffoldNavigator(
initialDestinationHistory = listOfNotNull(
ThreePaneScaffoldDestinationItem(ListDetailPaneScaffoldRole.List),
ThreePaneScaffoldDestinationItem<Nothing>(ListDetailPaneScaffoldRole.Detail).takeIf {
selectedTopicId != null
},
),
)
BackHandler(listDetailNavigator.canNavigateBack()) {
listDetailNavigator.navigateBack()
}

var isNestedNavHostInitialized by remember { mutableStateOf(false) }
var pendingNestedNavControllerNavigationTopicId by rememberSaveable {
mutableStateOf(selectedTopicId)
}

val nestedNavController = rememberNavController()

fun onTopicClickShowDetailPane(topicId: String) {
onTopicClick(topicId)
nestedNavController.navigateToTopic(topicId) {
popUpTo(DETAIL_PANE_NAVHOST_ROUTE)
if (isNestedNavHostInitialized) {
nestedNavController.navigateToTopic(topicId) {
popUpTo(DETAIL_PANE_NAVHOST_ROUTE)
}
} else {
// If the nested nav host hasn't been initialized, it isn't safe to call
// navigate yet. Put the topic id into a state to navigate later
pendingNestedNavControllerNavigationTopicId = topicId
}
listDetailNavigator.navigateTo(ListDetailPaneScaffoldRole.Detail)
}
Expand All @@ -95,34 +119,47 @@ internal fun InterestsListDetailScreen(
value = listDetailNavigator.scaffoldValue,
directive = listDetailNavigator.scaffoldDirective,
listPane = {
InterestsRoute(
onTopicClick = ::onTopicClickShowDetailPane,
highlightSelectedTopic = listDetailNavigator.isDetailPaneVisible(),
)
},
detailPane = {
NavHost(
navController = nestedNavController,
startDestination = TOPIC_ROUTE,
route = DETAIL_PANE_NAVHOST_ROUTE,
) {
topicScreen(
showBackButton = !listDetailNavigator.isListPaneVisible(),
onBackClick = listDetailNavigator::navigateBack,
AnimatedPane {
InterestsRoute(
onTopicClick = ::onTopicClickShowDetailPane,
highlightSelectedTopic = listDetailNavigator.isDetailPaneVisible(),
)
composable(route = TOPIC_ROUTE) {
TopicDetailPlaceholder()
}
},
detailPane = {
AnimatedPane {
NavHost(
navController = nestedNavController,
startDestination = TOPIC_ROUTE,
route = DETAIL_PANE_NAVHOST_ROUTE,
) {
topicScreen(
showBackButton = !listDetailNavigator.isListPaneVisible(),
onBackClick = listDetailNavigator::navigateBack,
onTopicClick = ::onTopicClickShowDetailPane,
)
composable(route = TOPIC_ROUTE) {
TopicDetailPlaceholder()
}
}
SideEffect {
// We have now successfully ran NavHost
isNestedNavHostInitialized = true
// Check if there was a pending navigation to invoke
val currentPendingNestedNavControllerNavigationTopicId =
pendingNestedNavControllerNavigationTopicId
if (currentPendingNestedNavControllerNavigationTopicId != null) {
nestedNavController.navigateToTopic(
currentPendingNestedNavControllerNavigationTopicId,
) {
popUpTo(DETAIL_PANE_NAVHOST_ROUTE)
}
pendingNestedNavControllerNavigationTopicId = null
}
}
}
},
)
LaunchedEffect(Unit) {
if (selectedTopicId != null) {
// Initial topic ID was provided when navigating to Interests, so show its details.
onTopicClickShowDetailPane(selectedTopicId)
}
}
}

@OptIn(ExperimentalMaterial3AdaptiveApi::class)
Expand Down
Expand Up @@ -41,13 +41,16 @@ internal class TopicArgs(val topicId: String) {
}

fun NavController.navigateToTopic(topicId: String, navOptions: NavOptionsBuilder.() -> Unit = {}) {
val encodedId = URLEncoder.encode(topicId, URL_CHARACTER_ENCODING)
val newRoute = "$TOPIC_ROUTE/$encodedId"
navigate(newRoute) {
navigate(createTopicRoute(topicId)) {
navOptions()
}
}

fun createTopicRoute(topicId: String): String {
val encodedId = URLEncoder.encode(topicId, URL_CHARACTER_ENCODING)
return "$TOPIC_ROUTE/$encodedId"
}

fun NavGraphBuilder.topicScreen(
showBackButton: Boolean,
onBackClick: () -> Unit,
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Expand Up @@ -20,7 +20,7 @@ androidxHiltNavigationCompose = "1.2.0"
androidxLifecycle = "2.7.0"
androidxMacroBenchmark = "1.2.2"
androidxMetrics = "1.0.0-alpha04"
androidxNavigation = "2.7.4"
androidxNavigation = "2.8.0-alpha06"
androidxProfileinstaller = "1.3.1"
androidxTestCore = "1.5.0"
androidxTestExt = "1.1.5"
Expand Down