1+ package com.example.compose.snippets.predictiveback
2+
3+ import androidx.compose.runtime.Composable
4+ import androidx.compose.ui.Modifier
5+ import androidx.navigation.compose.NavHost
6+ import androidx.navigation.compose.rememberNavController
7+ import androidx.navigation.NavHostController
8+ import androidx.compose.animation.scaleOut
9+ import androidx.compose.ui.graphics.TransformOrigin
10+ import androidx.compose.animation.EnterTransition
11+ import android.os.SystemClock
12+ import androidx.activity.compose.PredictiveBackHandler
13+ import androidx.compose.ui.unit.dp
14+ import androidx.compose.animation.core.Animatable
15+ import androidx.navigation.compose.composable
16+ import androidx.compose.foundation.layout.fillMaxSize
17+ import androidx.compose.material3.Surface
18+ import androidx.compose.runtime.getValue
19+ import androidx.compose.runtime.mutableStateOf
20+ import androidx.compose.runtime.remember
21+ import androidx.compose.runtime.rememberCoroutineScope
22+ import androidx.compose.runtime.setValue
23+ import androidx.compose.ui.geometry.Offset
24+ import androidx.compose.ui.input.pointer.util.VelocityTracker
25+ import androidx.compose.ui.platform.LocalDensity
26+ import kotlin.coroutines.cancellation.CancellationException
27+
28+
29+ @Composable
30+ private fun PredictiveBackOverrideExit (
31+ modifier : Modifier ,
32+ ) {
33+ val navController = rememberNavController()
34+
35+ // [START android_compose_predictiveback_navhost]
36+ NavHost (
37+ navController = navController,
38+ startDestination = " home" ,
39+ popExitTransition = {
40+ scaleOut(
41+ targetScale = 0.9f ,
42+ transformOrigin = TransformOrigin (pivotFractionX = 0.5f , pivotFractionY = 0.5f )
43+ )
44+ },
45+ popEnterTransition = {
46+ EnterTransition .None
47+ },
48+ modifier = modifier,
49+ )
50+ // [END android_compose_predictiveback_navhost]
51+ {
52+ composable(" home" ) {
53+ HomeScreen (
54+ modifier = modifier,
55+ navController = navController,
56+ )
57+ }
58+ composable(" settings" ) {
59+ SettingsScreen (
60+ modifier = modifier,
61+ navController = navController,
62+ )
63+ }
64+ }
65+ }
66+
67+ @Composable
68+ private fun HomeScreen (
69+ modifier : Modifier = Modifier , navController : NavHostController
70+ ) {
71+
72+ }
73+
74+ @Composable
75+ private fun SettingsScreen (
76+ modifier : Modifier = Modifier , navController : NavHostController
77+ ) {
78+
79+ }
80+
81+ @Composable
82+ private fun PredictiveBackHandlerManualProgress () {
83+
84+ Surface (
85+ modifier = Modifier .fillMaxSize()
86+ ) {
87+ var drawerState by remember {
88+ mutableStateOf(DrawerState .Closed )
89+ }
90+
91+ val translationX = remember {
92+ Animatable (0f )
93+ }
94+
95+ val drawerWidth = with (LocalDensity .current) {
96+ DrawerWidth .toPx()
97+ }
98+ translationX.updateBounds(0f , drawerWidth)
99+
100+ val coroutineScope = rememberCoroutineScope()
101+
102+ suspend fun closeDrawer (velocity : Float = 0f) {
103+ translationX.animateTo(targetValue = 0f , initialVelocity = velocity)
104+ drawerState = DrawerState .Closed
105+ }
106+ suspend fun openDrawer (velocity : Float = 0f) {
107+ translationX.animateTo(targetValue = drawerWidth, initialVelocity = velocity)
108+ drawerState = DrawerState .Open
109+ }
110+
111+ val velocityTracker = remember {
112+ VelocityTracker ()
113+ }
114+
115+ // [START android_compose_predictivebackhandler]
116+ PredictiveBackHandler (drawerState == DrawerState .Open ) { progress ->
117+ try {
118+ progress.collect { backEvent ->
119+ val targetSize = (drawerWidth - (drawerWidth * backEvent.progress))
120+ translationX.snapTo(targetSize)
121+ velocityTracker.addPosition(
122+ SystemClock .uptimeMillis(),
123+ Offset (backEvent.touchX, backEvent.touchY)
124+ )
125+ }
126+ closeDrawer(velocityTracker.calculateVelocity().x)
127+ } catch (e: CancellationException ) {
128+ openDrawer(velocityTracker.calculateVelocity().x)
129+ }
130+ velocityTracker.resetTracking()
131+ }
132+ // [END android_compose_predictivebackhandler]
133+
134+ }
135+ }
136+
137+ private enum class DrawerState {
138+ Open ,
139+ Closed
140+ }
141+
142+ private val DrawerWidth = 300 .dp
0 commit comments