Skip to content

Commit 2553411

Browse files
committed
Add predictive back and pane expansion back handling
Change-Id: I8e881bb2cf549303be8612732bfb7df7555096aa
1 parent 800e3d5 commit 2553411

File tree

4 files changed

+38
-30
lines changed

4 files changed

+38
-30
lines changed

app/src/main/kotlin/com/google/samples/apps/nowinandroid/NiaApplication.kt

+3-5
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ package com.google.samples.apps.nowinandroid
1818

1919
import android.app.Application
2020
import android.content.pm.ApplicationInfo
21-
import android.os.StrictMode
22-
import android.os.StrictMode.ThreadPolicy.Builder
2321
import coil.ImageLoader
2422
import coil.ImageLoaderFactory
2523
import com.google.samples.apps.nowinandroid.sync.initializers.Sync
@@ -65,9 +63,9 @@ class NiaApplication : Application(), ImageLoaderFactory {
6563
*/
6664
private fun setStrictModePolicy() {
6765
if (isDebuggable()) {
68-
StrictMode.setThreadPolicy(
69-
Builder().detectAll().penaltyLog().penaltyDeath().build(),
70-
)
66+
// StrictMode.setThreadPolicy(
67+
// Builder().detectAll().penaltyLog().penaltyDeath().build(),
68+
// )
7169
}
7270
}
7371
}

app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/interests2pane/InterestsListDetailScreen.kt

+23-22
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package com.google.samples.apps.nowinandroid.ui.interests2pane
1818

1919
import androidx.activity.compose.BackHandler
20-
import androidx.annotation.Keep
2120
import androidx.compose.animation.AnimatedContent
2221
import androidx.compose.foundation.interaction.MutableInteractionSource
2322
import androidx.compose.foundation.layout.Box
@@ -27,55 +26,44 @@ import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
2726
import androidx.compose.material3.adaptive.WindowAdaptiveInfo
2827
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
2928
import androidx.compose.material3.adaptive.layout.AnimatedPane
30-
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffold
3129
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole
3230
import androidx.compose.material3.adaptive.layout.PaneAdaptedValue
3331
import androidx.compose.material3.adaptive.layout.PaneExpansionAnchor
3432
import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem
3533
import androidx.compose.material3.adaptive.layout.calculatePaneScaffoldDirective
34+
import androidx.compose.material3.adaptive.layout.defaultDragHandleSemantics
3635
import androidx.compose.material3.adaptive.layout.rememberPaneExpansionState
36+
import androidx.compose.material3.adaptive.navigation.BackNavigationBehavior
37+
import androidx.compose.material3.adaptive.navigation.NavigableListDetailPaneScaffold
3738
import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator
39+
import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldPredictiveBackHandler
3840
import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator
3941
import androidx.compose.runtime.Composable
4042
import androidx.compose.runtime.getValue
41-
import androidx.compose.runtime.key
4243
import androidx.compose.runtime.mutableStateOf
4344
import androidx.compose.runtime.remember
4445
import androidx.compose.runtime.rememberCoroutineScope
45-
import androidx.compose.runtime.saveable.Saver
46-
import androidx.compose.runtime.saveable.rememberSaveable
4746
import androidx.compose.runtime.setValue
4847
import androidx.compose.ui.Modifier
4948
import androidx.compose.ui.draw.clipToBounds
5049
import androidx.compose.ui.layout.layout
5150
import androidx.compose.ui.unit.dp
5251
import androidx.hilt.navigation.compose.hiltViewModel
5352
import androidx.lifecycle.compose.collectAsStateWithLifecycle
54-
import androidx.lifecycle.viewmodel.viewModelFactory
5553
import androidx.navigation.NavGraphBuilder
56-
import androidx.navigation.compose.NavHost
5754
import androidx.navigation.compose.composable
58-
import androidx.navigation.compose.rememberNavController
5955
import com.google.samples.apps.nowinandroid.feature.interests.InterestsRoute
6056
import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsRoute
6157
import com.google.samples.apps.nowinandroid.feature.topic.TopicDetailPlaceholder
6258
import com.google.samples.apps.nowinandroid.feature.topic.TopicScreen
6359
import com.google.samples.apps.nowinandroid.feature.topic.TopicViewModel
64-
import com.google.samples.apps.nowinandroid.feature.topic.TopicViewModel_Factory
6560
import com.google.samples.apps.nowinandroid.feature.topic.navigation.TopicRoute
66-
import com.google.samples.apps.nowinandroid.feature.topic.navigation.navigateToTopic
67-
import com.google.samples.apps.nowinandroid.feature.topic.navigation.topicScreen
6861
import kotlinx.coroutines.launch
6962
import kotlinx.serialization.Serializable
70-
import java.util.UUID
7163
import kotlin.math.max
7264

7365
@Serializable internal object TopicPlaceholderRoute
7466

75-
// TODO: Remove @Keep when https://issuetracker.google.com/353898971 is fixed
76-
@Keep
77-
@Serializable internal object DetailPaneNavHostRoute
78-
7967
fun NavGraphBuilder.interestsListDetailScreen() {
8068
composable<InterestsRoute> {
8169
InterestsListDetailScreen()
@@ -121,9 +109,17 @@ internal fun InterestsListDetailScreen(
121109
),
122110
)
123111

124-
BackHandler(listDetailNavigator.canNavigateBack()) {
112+
ThreePaneScaffoldPredictiveBackHandler(
113+
listDetailNavigator,
114+
BackNavigationBehavior.PopUntilScaffoldValueChange,
115+
)
116+
BackHandler(
117+
paneExpansionState.currentAnchor == PaneExpansionAnchor.Proportion(0f) &&
118+
listDetailNavigator.isListPaneVisible() &&
119+
listDetailNavigator.isDetailPaneVisible(),
120+
) {
125121
coroutineScope.launch {
126-
listDetailNavigator.navigateBack()
122+
paneExpansionState.animateTo(PaneExpansionAnchor.Proportion(1f))
127123
}
128124
}
129125

@@ -138,14 +134,18 @@ internal fun InterestsListDetailScreen(
138134
coroutineScope.launch {
139135
listDetailNavigator.navigateTo(ListDetailPaneScaffoldRole.Detail)
140136
}
137+
if (paneExpansionState.currentAnchor == PaneExpansionAnchor.Proportion(1f)) {
138+
coroutineScope.launch {
139+
paneExpansionState.animateTo(PaneExpansionAnchor.Proportion(0f))
140+
}
141+
}
141142
}
142143

143144
val mutableInteractionSource = remember { MutableInteractionSource() }
144145
val minPaneWidth = 300.dp
145146

146-
ListDetailPaneScaffold(
147-
value = listDetailNavigator.scaffoldValue,
148-
directive = listDetailNavigator.scaffoldDirective,
147+
NavigableListDetailPaneScaffold(
148+
navigator = listDetailNavigator,
149149
listPane = {
150150
AnimatedPane {
151151
Box(
@@ -209,7 +209,7 @@ internal fun InterestsListDetailScreen(
209209
key = route.id,
210210
) { factory ->
211211
factory.create(route.id)
212-
}
212+
},
213213
)
214214
}
215215
is TopicPlaceholderRoute -> {
@@ -227,6 +227,7 @@ internal fun InterestsListDetailScreen(
227227
state = paneExpansionState,
228228
minTouchTargetSize = LocalMinimumInteractiveComponentSize.current,
229229
interactionSource = mutableInteractionSource,
230+
semanticsProperties = paneExpansionState.defaultDragHandleSemantics(),
230231
),
231232
interactionSource = mutableInteractionSource,
232233
)

feature/topic/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/navigation/TopicNavigation.kt

+10-1
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@
1616

1717
package com.google.samples.apps.nowinandroid.feature.topic.navigation
1818

19+
import androidx.hilt.navigation.compose.hiltViewModel
1920
import androidx.navigation.NavController
2021
import androidx.navigation.NavGraphBuilder
2122
import androidx.navigation.NavOptionsBuilder
2223
import androidx.navigation.compose.composable
24+
import androidx.navigation.toRoute
2325
import com.google.samples.apps.nowinandroid.feature.topic.TopicScreen
26+
import com.google.samples.apps.nowinandroid.feature.topic.TopicViewModel
2427
import kotlinx.serialization.Serializable
2528

2629
@Serializable data class TopicRoute(val id: String)
@@ -36,11 +39,17 @@ fun NavGraphBuilder.topicScreen(
3639
onBackClick: () -> Unit,
3740
onTopicClick: (String) -> Unit,
3841
) {
39-
composable<TopicRoute> {
42+
composable<TopicRoute> { entry ->
43+
val id = entry.toRoute<TopicRoute>().id
4044
TopicScreen(
4145
showBackButton = showBackButton,
4246
onBackClick = onBackClick,
4347
onTopicClick = onTopicClick,
48+
viewModel = hiltViewModel<TopicViewModel, TopicViewModel.Factory>(
49+
key = id,
50+
) { factory ->
51+
factory.create(id)
52+
},
4453
)
4554
}
4655
}

gradle/libs.versions.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ androidTools = "31.7.3"
77
androidxActivity = "1.9.3"
88
androidxAppCompat = "1.7.0"
99
androidxBrowser = "1.8.0"
10-
androidxComposeBom = "2024.12.01"
10+
androidxComposeBom = "2025.02.00"
1111
androidxComposeFoundation = "1.8.0-alpha07"
12-
androidxComposeMaterial3Adaptive = "1.1.0-alpha08"
12+
androidxComposeMaterial3Adaptive = "1.1.0-rc01"
1313
androidxComposeRuntimeTracing = "1.7.6"
1414
androidxCore = "1.15.0"
1515
androidxCoreSplashscreen = "1.0.1"

0 commit comments

Comments
 (0)