Skip to content

Commit 215d996

Browse files
add popUpTo, launchTop sample
1 parent 888ba53 commit 215d996

File tree

1 file changed

+305
-0
lines changed
  • Tutorial3-1Navigation/src/main/java/com/smarttoolfactory/tutorial3_1navigation

1 file changed

+305
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
package com.smarttoolfactory.tutorial3_1navigation
2+
3+
import android.annotation.SuppressLint
4+
import androidx.compose.animation.AnimatedContentTransitionScope.SlideDirection
5+
import androidx.compose.animation.core.tween
6+
import androidx.compose.foundation.background
7+
import androidx.compose.foundation.clickable
8+
import androidx.compose.foundation.layout.Arrangement
9+
import androidx.compose.foundation.layout.Column
10+
import androidx.compose.foundation.layout.PaddingValues
11+
import androidx.compose.foundation.layout.Row
12+
import androidx.compose.foundation.layout.Spacer
13+
import androidx.compose.foundation.layout.fillMaxSize
14+
import androidx.compose.foundation.layout.fillMaxWidth
15+
import androidx.compose.foundation.layout.padding
16+
import androidx.compose.foundation.layout.width
17+
import androidx.compose.foundation.rememberScrollState
18+
import androidx.compose.foundation.verticalScroll
19+
import androidx.compose.material3.Button
20+
import androidx.compose.material3.Checkbox
21+
import androidx.compose.material3.Scaffold
22+
import androidx.compose.material3.Text
23+
import androidx.compose.runtime.Composable
24+
import androidx.compose.runtime.collectAsState
25+
import androidx.compose.runtime.getValue
26+
import androidx.compose.runtime.mutableStateOf
27+
import androidx.compose.runtime.remember
28+
import androidx.compose.runtime.setValue
29+
import androidx.compose.ui.Alignment
30+
import androidx.compose.ui.Modifier
31+
import androidx.compose.ui.graphics.Color
32+
import androidx.compose.ui.tooling.preview.Preview
33+
import androidx.compose.ui.unit.dp
34+
import androidx.navigation.NavBackStackEntry
35+
import androidx.navigation.NavController
36+
import androidx.navigation.compose.NavHost
37+
import androidx.navigation.compose.composable
38+
import androidx.navigation.compose.rememberNavController
39+
40+
@Preview
41+
@Composable
42+
fun Tutorial2Screen() {
43+
val navController = rememberNavController()
44+
45+
Scaffold { innerPadding: PaddingValues ->
46+
NavHost(
47+
modifier = Modifier
48+
.padding(innerPadding)
49+
.fillMaxSize(),
50+
navController = navController,
51+
startDestination = RouteA,
52+
enterTransition = {
53+
slideIntoContainer(
54+
towards = SlideDirection.Start,
55+
animationSpec = tween(700)
56+
)
57+
},
58+
exitTransition = {
59+
slideOutOfContainer(
60+
towards = SlideDirection.End,
61+
animationSpec = tween(700)
62+
)
63+
},
64+
popEnterTransition = {
65+
slideIntoContainer(
66+
towards = SlideDirection.Start,
67+
animationSpec = tween(700)
68+
)
69+
},
70+
popExitTransition = {
71+
slideOutOfContainer(
72+
towards = SlideDirection.End,
73+
animationSpec = tween(700)
74+
)
75+
}
76+
) {
77+
composable<RouteA> {
78+
RouteAScreen(navController)
79+
}
80+
81+
composable<RouteB> {
82+
RouteBScreen(navController)
83+
}
84+
85+
composable<RouteC> {
86+
RouteCScreen(navController)
87+
}
88+
89+
composable<RouteD> {
90+
RouteDScreen(navController)
91+
}
92+
}
93+
}
94+
}
95+
96+
@Composable
97+
private fun RouteAScreen(navController: NavController) {
98+
RouteScreen(
99+
modifier = Modifier.background(Color.White),
100+
title = "RouteAScreen",
101+
navController = navController
102+
)
103+
}
104+
105+
@Composable
106+
private fun RouteBScreen(navController: NavController) {
107+
RouteScreen(
108+
modifier = Modifier.background(Color.Cyan),
109+
title = "RouteBScreen",
110+
navController = navController
111+
)
112+
}
113+
114+
@Composable
115+
private fun RouteCScreen(navController: NavController) {
116+
RouteScreen(
117+
modifier = Modifier.background(Color.Yellow),
118+
title = "RouteCScreen",
119+
navController = navController
120+
)
121+
}
122+
123+
@Composable
124+
private fun RouteDScreen(navController: NavController) {
125+
RouteScreen(
126+
modifier = Modifier.background(Color.Green),
127+
title = "RouteDScreen",
128+
navController = navController
129+
)
130+
}
131+
132+
@SuppressLint("RestrictedApi")
133+
@Composable
134+
private fun RouteScreen(
135+
modifier: Modifier = Modifier,
136+
title: String,
137+
navController: NavController,
138+
) {
139+
140+
var popUpToInclusive by remember {
141+
mutableStateOf(false)
142+
}
143+
144+
var isSingleTop by remember {
145+
mutableStateOf(false)
146+
}
147+
148+
Column(
149+
modifier = modifier
150+
.fillMaxSize()
151+
.padding(16.dp),
152+
verticalArrangement = Arrangement.spacedBy(8.dp)
153+
) {
154+
155+
156+
Text(title)
157+
158+
159+
var popUpToRoute by remember { mutableStateOf<Any?>(null) }
160+
161+
162+
ExposedSelectionMenu(title = "PopUpTo",
163+
index = when (popUpToRoute) {
164+
null -> 0
165+
RouteA -> 1
166+
RouteB -> 2
167+
RouteC -> 3
168+
else -> 4
169+
},
170+
options = listOf("no popUpTo", "RouteA", "RouteB", "RouteC", "RouteD"),
171+
onSelected = {
172+
popUpToRoute = when (it) {
173+
0 -> null
174+
1 -> RouteA
175+
2 -> RouteB
176+
3 -> RouteC
177+
else -> RouteD
178+
}
179+
}
180+
)
181+
182+
Row {
183+
CheckBoxWithText(
184+
title = "popUpToInclusive",
185+
enabled = popUpToRoute != null,
186+
checked = popUpToInclusive
187+
) {
188+
popUpToInclusive = it
189+
}
190+
191+
Spacer(Modifier.width(8.dp))
192+
193+
CheckBoxWithText(
194+
title = "singleTop",
195+
checked = isSingleTop
196+
) {
197+
isSingleTop = it
198+
}
199+
}
200+
201+
NavigationButton(
202+
navController = navController,
203+
title = "RouteA",
204+
targetRoute = RouteA,
205+
popUpToRoute = popUpToRoute,
206+
popUpToInclusive = popUpToInclusive,
207+
singleTop = isSingleTop
208+
)
209+
210+
NavigationButton(
211+
navController = navController,
212+
title = "RouteB",
213+
targetRoute = RouteB,
214+
popUpToRoute = popUpToRoute,
215+
popUpToInclusive = popUpToInclusive,
216+
singleTop = isSingleTop
217+
)
218+
219+
NavigationButton(
220+
navController = navController,
221+
title = "RouteC",
222+
targetRoute = RouteC,
223+
popUpToRoute = popUpToRoute,
224+
popUpToInclusive = popUpToInclusive,
225+
singleTop = isSingleTop
226+
)
227+
228+
NavigationButton(
229+
navController = navController,
230+
title = "RouteD",
231+
targetRoute = RouteD,
232+
popUpToRoute = popUpToRoute,
233+
popUpToInclusive = popUpToInclusive,
234+
singleTop = isSingleTop
235+
)
236+
237+
val backStack: List<NavBackStackEntry> by navController.currentBackStack.collectAsState()
238+
239+
Column(
240+
modifier = Modifier.verticalScroll(rememberScrollState())
241+
) {
242+
backStack.reversed().forEach {
243+
Text(
244+
text = it.destination.route ?: it.destination.displayName,
245+
modifier = Modifier.fillMaxWidth()
246+
)
247+
}
248+
}
249+
}
250+
}
251+
252+
@Composable
253+
private fun NavigationButton(
254+
navController: NavController,
255+
title: String,
256+
targetRoute: Any,
257+
popUpToRoute: Any? = null,
258+
popUpToInclusive: Boolean,
259+
singleTop: Boolean,
260+
) {
261+
Button(
262+
modifier = Modifier.fillMaxWidth(),
263+
onClick = {
264+
navController.navigate(
265+
route = targetRoute
266+
) {
267+
popUpToRoute?.let {
268+
popUpTo(
269+
route = it
270+
) {
271+
inclusive = popUpToInclusive
272+
}
273+
}
274+
275+
launchSingleTop = singleTop
276+
}
277+
}
278+
) {
279+
Text("Navigate to $title")
280+
}
281+
}
282+
283+
@Composable
284+
private fun CheckBoxWithText(
285+
modifier: Modifier = Modifier,
286+
title: String,
287+
enabled: Boolean = true,
288+
checked: Boolean,
289+
onCheckChange: (Boolean) -> Unit,
290+
) {
291+
Row(
292+
modifier = modifier
293+
.clickable(
294+
enabled = enabled
295+
) {
296+
onCheckChange(checked.not())
297+
}
298+
.padding(8.dp),
299+
verticalAlignment = Alignment.CenterVertically
300+
) {
301+
Checkbox(checked = checked, onCheckedChange = null, enabled = enabled)
302+
Spacer(Modifier.width(16.dp))
303+
Text(title)
304+
}
305+
}

0 commit comments

Comments
 (0)