Add predictive back and pane expansion back handling

Change-Id: I8e881bb2cf549303be8612732bfb7df7555096aa
pull/1837/head
Alex Vanyo 6 months ago
parent ff78308055
commit 05e4e4de31

@ -17,7 +17,6 @@
package com.google.samples.apps.nowinandroid.ui.interests2pane
import androidx.activity.compose.BackHandler
import androidx.annotation.Keep
import androidx.compose.animation.AnimatedContent
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
@ -27,23 +26,23 @@ import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
import androidx.compose.material3.adaptive.WindowAdaptiveInfo
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
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.PaneExpansionAnchor
import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem
import androidx.compose.material3.adaptive.layout.calculatePaneScaffoldDirective
import androidx.compose.material3.adaptive.layout.defaultDragHandleSemantics
import androidx.compose.material3.adaptive.layout.rememberPaneExpansionState
import androidx.compose.material3.adaptive.navigation.BackNavigationBehavior
import androidx.compose.material3.adaptive.navigation.NavigableListDetailPaneScaffold
import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator
import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldPredictiveBackHandler
import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clipToBounds
@ -51,31 +50,20 @@ import androidx.compose.ui.layout.layout
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.viewModelFactory
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.google.samples.apps.nowinandroid.feature.interests.InterestsRoute
import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsRoute
import com.google.samples.apps.nowinandroid.feature.topic.TopicDetailPlaceholder
import com.google.samples.apps.nowinandroid.feature.topic.TopicScreen
import com.google.samples.apps.nowinandroid.feature.topic.TopicViewModel
import com.google.samples.apps.nowinandroid.feature.topic.TopicViewModel_Factory
import com.google.samples.apps.nowinandroid.feature.topic.navigation.TopicRoute
import com.google.samples.apps.nowinandroid.feature.topic.navigation.navigateToTopic
import com.google.samples.apps.nowinandroid.feature.topic.navigation.topicScreen
import kotlinx.coroutines.launch
import kotlinx.serialization.Serializable
import java.util.UUID
import kotlin.math.max
@Serializable internal object TopicPlaceholderRoute
// TODO: Remove @Keep when https://issuetracker.google.com/353898971 is fixed
@Keep
@Serializable internal object DetailPaneNavHostRoute
fun NavGraphBuilder.interestsListDetailScreen() {
composable<InterestsRoute> {
InterestsListDetailScreen()
@ -121,9 +109,17 @@ internal fun InterestsListDetailScreen(
),
)
BackHandler(listDetailNavigator.canNavigateBack()) {
ThreePaneScaffoldPredictiveBackHandler(
listDetailNavigator,
BackNavigationBehavior.PopUntilScaffoldValueChange,
)
BackHandler(
paneExpansionState.currentAnchor == PaneExpansionAnchor.Proportion(0f) &&
listDetailNavigator.isListPaneVisible() &&
listDetailNavigator.isDetailPaneVisible(),
) {
coroutineScope.launch {
listDetailNavigator.navigateBack()
paneExpansionState.animateTo(PaneExpansionAnchor.Proportion(1f))
}
}
@ -138,14 +134,18 @@ internal fun InterestsListDetailScreen(
coroutineScope.launch {
listDetailNavigator.navigateTo(ListDetailPaneScaffoldRole.Detail)
}
if (paneExpansionState.currentAnchor == PaneExpansionAnchor.Proportion(1f)) {
coroutineScope.launch {
paneExpansionState.animateTo(PaneExpansionAnchor.Proportion(0f))
}
}
}
val mutableInteractionSource = remember { MutableInteractionSource() }
val minPaneWidth = 300.dp
ListDetailPaneScaffold(
value = listDetailNavigator.scaffoldValue,
directive = listDetailNavigator.scaffoldDirective,
NavigableListDetailPaneScaffold(
navigator = listDetailNavigator,
listPane = {
AnimatedPane {
Box(
@ -209,7 +209,7 @@ internal fun InterestsListDetailScreen(
key = route.id,
) { factory ->
factory.create(route.id)
}
},
)
}
is TopicPlaceholderRoute -> {
@ -227,6 +227,7 @@ internal fun InterestsListDetailScreen(
state = paneExpansionState,
minTouchTargetSize = LocalMinimumInteractiveComponentSize.current,
interactionSource = mutableInteractionSource,
semanticsProperties = paneExpansionState.defaultDragHandleSemantics(),
),
interactionSource = mutableInteractionSource,
)

@ -16,11 +16,14 @@
package com.google.samples.apps.nowinandroid.feature.topic.navigation
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptionsBuilder
import androidx.navigation.compose.composable
import androidx.navigation.toRoute
import com.google.samples.apps.nowinandroid.feature.topic.TopicScreen
import com.google.samples.apps.nowinandroid.feature.topic.TopicViewModel
import kotlinx.serialization.Serializable
@Serializable data class TopicRoute(val id: String)
@ -36,11 +39,17 @@ fun NavGraphBuilder.topicScreen(
onBackClick: () -> Unit,
onTopicClick: (String) -> Unit,
) {
composable<TopicRoute> {
composable<TopicRoute> { entry ->
val id = entry.toRoute<TopicRoute>().id
TopicScreen(
showBackButton = showBackButton,
onBackClick = onBackClick,
onTopicClick = onTopicClick,
viewModel = hiltViewModel<TopicViewModel, TopicViewModel.Factory>(
key = id,
) { factory ->
factory.create(id)
},
)
}
}

@ -7,9 +7,9 @@ androidTools = "31.7.3"
androidxActivity = "1.9.3"
androidxAppCompat = "1.7.0"
androidxBrowser = "1.8.0"
androidxComposeBom = "2024.12.01"
androidxComposeBom = "2025.02.00"
androidxComposeFoundation = "1.8.0-alpha07"
androidxComposeMaterial3Adaptive = "1.1.0-alpha08"
androidxComposeMaterial3Adaptive = "1.1.0-rc01"
androidxComposeRuntimeTracing = "1.7.6"
androidxCore = "1.15.0"
androidxCoreSplashscreen = "1.0.1"

Loading…
Cancel
Save