Skip to content

Commit 89507d5

Browse files
committed
Add navigation3 snippets
1 parent 1da1d9d commit 89507d5

File tree

9 files changed

+847
-1
lines changed

9 files changed

+847
-1
lines changed

compose/snippets/build.gradle.kts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ dependencies {
9595
implementation(libs.androidx.compose.material3.adaptive.layout)
9696
implementation(libs.androidx.compose.material3.adaptive.navigation)
9797
implementation(libs.androidx.compose.material3.adaptive.navigation.suite)
98+
implementation(libs.androidx.compose.material3.windowsizeclass)
9899
implementation(libs.androidx.compose.material)
99100

100101
implementation(libs.androidx.compose.runtime)
@@ -136,7 +137,13 @@ dependencies {
136137
implementation(libs.androidx.navigation.compose)
137138
implementation(libs.hilt.android)
138139
implementation(libs.androidx.hilt.navigation.compose)
140+
141+
implementation(libs.kotlinx.serialization.core)
139142
implementation(libs.kotlinx.serialization.json)
143+
implementation(libs.androidx.compose.material3.adaptive.navigation3)
144+
implementation(libs.androidx.navigation3.runtime)
145+
implementation(libs.androidx.navigation3.ui)
146+
implementation(libs.androidx.lifecycle.viewmodel.navigation3)
140147

141148
implementation(libs.androidx.recyclerview)
142149

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/*
2+
* Copyright 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.compose.snippets.navigation3
18+
19+
import androidx.compose.animation.ExperimentalSharedTransitionApi
20+
import androidx.compose.foundation.background
21+
import androidx.compose.foundation.layout.Column
22+
import androidx.compose.foundation.layout.ColumnScope
23+
import androidx.compose.foundation.layout.fillMaxSize
24+
import androidx.compose.foundation.layout.padding
25+
import androidx.compose.foundation.shape.RoundedCornerShape
26+
import androidx.compose.material3.Button
27+
import androidx.compose.material3.Text
28+
import androidx.compose.runtime.Composable
29+
import androidx.compose.ui.Alignment
30+
import androidx.compose.ui.Modifier
31+
import androidx.compose.ui.draw.clip
32+
import androidx.compose.ui.graphics.Color
33+
import androidx.compose.ui.text.font.FontWeight
34+
import androidx.compose.ui.unit.dp
35+
import com.example.compose.snippets.ui.theme.PastelBlue
36+
import com.example.compose.snippets.ui.theme.PastelGreen
37+
import com.example.compose.snippets.ui.theme.PastelMauve
38+
import com.example.compose.snippets.ui.theme.PastelOrange
39+
import com.example.compose.snippets.ui.theme.PastelPink
40+
import com.example.compose.snippets.ui.theme.PastelPurple
41+
import com.example.compose.snippets.ui.theme.PastelRed
42+
import com.example.compose.snippets.ui.theme.PastelYellow
43+
44+
@OptIn(ExperimentalSharedTransitionApi::class)
45+
@Composable
46+
fun ContentBase(
47+
title: String,
48+
modifier: Modifier = Modifier,
49+
onNext: (() -> Unit)? = null,
50+
content: (@Composable () -> Unit)? = null,
51+
) {
52+
Column(
53+
horizontalAlignment = Alignment.CenterHorizontally,
54+
modifier = modifier
55+
.fillMaxSize()
56+
.clip(RoundedCornerShape(48.dp))
57+
) {
58+
Title(title)
59+
if (content != null) content()
60+
if (onNext != null) {
61+
Button(
62+
modifier = Modifier.align(Alignment.CenterHorizontally),
63+
onClick = onNext
64+
) {
65+
Text("Next")
66+
}
67+
}
68+
}
69+
70+
}
71+
72+
@Composable
73+
fun ColumnScope.Title(title: String) {
74+
Text(
75+
modifier = Modifier
76+
.padding(24.dp)
77+
.align(Alignment.CenterHorizontally),
78+
fontWeight = FontWeight.Bold,
79+
text = title
80+
)
81+
}
82+
83+
@Composable
84+
fun ContentRed(
85+
title: String,
86+
modifier: Modifier = Modifier,
87+
onNext: (() -> Unit)? = null,
88+
content: (@Composable () -> Unit)? = null,
89+
) = ContentBase(
90+
title = title,
91+
modifier = modifier.background(PastelRed),
92+
onNext = onNext,
93+
content = content
94+
)
95+
96+
@Composable
97+
fun ContentOrange(
98+
title: String,
99+
modifier: Modifier = Modifier,
100+
onNext: (() -> Unit)? = null,
101+
content: (@Composable () -> Unit)? = null,
102+
) = ContentBase(
103+
title = title,
104+
modifier = modifier.background(PastelOrange),
105+
onNext = onNext,
106+
content = content
107+
)
108+
109+
@Composable
110+
fun ContentYellow(
111+
title: String,
112+
modifier: Modifier = Modifier,
113+
onNext: (() -> Unit)? = null,
114+
content: (@Composable () -> Unit)? = null,
115+
) = ContentBase(
116+
title = title,
117+
modifier = modifier.background(PastelYellow),
118+
onNext = onNext,
119+
content = content
120+
)
121+
122+
@Composable
123+
fun ContentGreen(
124+
title: String,
125+
modifier: Modifier = Modifier,
126+
onNext: (() -> Unit)? = null,
127+
content: (@Composable () -> Unit)? = null,
128+
) = ContentBase(
129+
title = title,
130+
modifier = modifier.background(PastelGreen),
131+
onNext = onNext,
132+
content = content
133+
)
134+
135+
@Composable
136+
fun ContentBlue(
137+
title: String,
138+
modifier: Modifier = Modifier,
139+
onNext: (() -> Unit)? = null,
140+
content: (@Composable () -> Unit)? = null,
141+
) = ContentBase(
142+
title = title,
143+
modifier = modifier.background(PastelBlue),
144+
onNext = onNext,
145+
content = content
146+
)
147+
148+
@Composable
149+
fun ContentMauve(
150+
title: String,
151+
modifier: Modifier = Modifier,
152+
onNext: (() -> Unit)? = null,
153+
content: (@Composable () -> Unit)? = null,
154+
) = ContentBase(
155+
title = title,
156+
modifier = modifier.background(PastelMauve),
157+
onNext = onNext,
158+
content = content
159+
)
160+
161+
@Composable
162+
fun ContentPurple(
163+
title: String,
164+
modifier: Modifier = Modifier,
165+
onNext: (() -> Unit)? = null,
166+
content: (@Composable () -> Unit)? = null,
167+
) = ContentBase(
168+
title = title,
169+
modifier = modifier.background(PastelPurple),
170+
onNext = onNext,
171+
content = content
172+
)
173+
174+
@Composable
175+
fun ContentPink(
176+
title: String,
177+
modifier: Modifier = Modifier,
178+
onNext: (() -> Unit)? = null,
179+
content: (@Composable () -> Unit)? = null,
180+
) = ContentBase(
181+
title = title,
182+
modifier = modifier.background(PastelPink),
183+
onNext = onNext,
184+
content = content
185+
)
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* Copyright 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.compose.snippets.navigation3.animations
18+
19+
import android.os.Bundle
20+
import androidx.activity.ComponentActivity
21+
import androidx.activity.compose.setContent
22+
import androidx.compose.animation.EnterTransition
23+
import androidx.compose.animation.ExitTransition
24+
import androidx.compose.animation.core.tween
25+
import androidx.compose.animation.slideInHorizontally
26+
import androidx.compose.animation.slideInVertically
27+
import androidx.compose.animation.slideOutHorizontally
28+
import androidx.compose.animation.slideOutVertically
29+
import androidx.compose.animation.togetherWith
30+
import androidx.compose.foundation.layout.padding
31+
import androidx.compose.material3.Button
32+
import androidx.compose.material3.Scaffold
33+
import androidx.compose.material3.Text
34+
import androidx.compose.ui.Modifier
35+
import androidx.navigation3.runtime.NavKey
36+
import androidx.navigation3.runtime.entry
37+
import androidx.navigation3.runtime.entryProvider
38+
import androidx.navigation3.runtime.rememberNavBackStack
39+
import androidx.navigation3.ui.NavDisplay
40+
import com.example.compose.snippets.navigation3.ContentGreen
41+
import com.example.compose.snippets.navigation3.ContentMauve
42+
import com.example.compose.snippets.navigation3.ContentOrange
43+
import kotlinx.serialization.Serializable
44+
45+
// [START android_compose_navigation3_animations_1]
46+
@Serializable
47+
data object ScreenA : NavKey
48+
49+
@Serializable
50+
data object ScreenB : NavKey
51+
52+
@Serializable
53+
data object ScreenC : NavKey
54+
55+
56+
class AnimatedNavDisplayActivity : ComponentActivity() {
57+
58+
override fun onCreate(savedInstanceState: Bundle?) {
59+
super.onCreate(savedInstanceState)
60+
setContent {
61+
62+
Scaffold { paddingValues ->
63+
64+
val backStack = rememberNavBackStack(ScreenA)
65+
66+
NavDisplay(
67+
backStack = backStack,
68+
onBack = { backStack.removeLastOrNull() },
69+
entryProvider = entryProvider {
70+
entry<ScreenA> {
71+
ContentOrange("This is Screen A") {
72+
Button(onClick = { backStack.add(ScreenB) }) {
73+
Text("Go to Screen B")
74+
}
75+
}
76+
}
77+
entry<ScreenB> {
78+
ContentMauve("This is Screen B") {
79+
Button(onClick = { backStack.add(ScreenC) }) {
80+
Text("Go to Screen C")
81+
}
82+
}
83+
}
84+
entry<ScreenC>(
85+
metadata = NavDisplay.transitionSpec {
86+
// Slide new content up, keeping the old content in place underneath
87+
slideInVertically(
88+
initialOffsetY = { it },
89+
animationSpec = tween(1000)
90+
) togetherWith ExitTransition.KeepUntilTransitionsFinished
91+
} + NavDisplay.popTransitionSpec {
92+
// Slide old content down, revealing the new content in place underneath
93+
EnterTransition.None togetherWith
94+
slideOutVertically(
95+
targetOffsetY = { it },
96+
animationSpec = tween(1000)
97+
)
98+
} + NavDisplay.predictivePopTransitionSpec {
99+
// Slide old content down, revealing the new content in place underneath
100+
EnterTransition.None togetherWith
101+
slideOutVertically(
102+
targetOffsetY = { it },
103+
animationSpec = tween(1000)
104+
)
105+
}
106+
){
107+
ContentGreen("This is Screen C")
108+
}
109+
},
110+
transitionSpec = {
111+
// Slide in from right when navigating forward
112+
slideInHorizontally(initialOffsetX = { it }) togetherWith
113+
slideOutHorizontally(targetOffsetX = { -it })
114+
},
115+
popTransitionSpec = {
116+
// Slide in from left when navigating back
117+
slideInHorizontally(initialOffsetX = { -it }) togetherWith
118+
slideOutHorizontally(targetOffsetX = { it })
119+
},
120+
predictivePopTransitionSpec = {
121+
// Slide in from left when navigating back
122+
slideInHorizontally(initialOffsetX = { -it }) togetherWith
123+
slideOutHorizontally(targetOffsetX = { it })
124+
},
125+
modifier = Modifier.padding(paddingValues)
126+
)
127+
}
128+
}
129+
}
130+
}
131+
// [END android_compose_navigation3_animations_1]

0 commit comments

Comments
 (0)