Fixed
Status Update
Comments
cl...@google.com <cl...@google.com>
ap...@google.com <ap...@google.com> #2
Project: platform/frameworks/support
Branch: androidx-main
Author: Jeremy Woods <
Link:
Convert navigation-testing to KMP
Expand for full commit details
Convert navigation-testing to KMP
Moving the navigation-testing module to KMP. This supports all the same
platforms as the rest of Navigation and has converted all uses of Bundle
to the new SaveState.
RelNote: "Navigation Testing is now a KMP module."
Test: all tests pass
Bug: 398265336
Change-Id: I2b7707a56f263be30420cae57e3b38480d7f0625
Files:
- M
docs-tip-of-tree/build.gradle
- A
navigation/navigation-testing/bcv/native/current.txt
- M
navigation/navigation-testing/build.gradle
- M
navigation/navigation-testing/src/androidInstrumentedTest/AndroidManifest.xml
- M
navigation/navigation-testing/src/androidInstrumentedTest/kotlin/androidx/navigation/testing/TestNavHostControllerTest.kt
- M
navigation/navigation-testing/src/androidInstrumentedTest/kotlin/androidx/navigation/testing/TestNavigatorStateTest.kt
- M
navigation/navigation-testing/src/androidInstrumentedTest/res/navigation/test_graph.xml
- M
navigation/navigation-testing/src/androidMain/AndroidManifest.xml
- M
navigation/navigation-testing/src/androidMain/kotlin/androidx/navigation/testing/TestNavHostController.android.kt
- M
navigation/navigation-testing/src/androidMain/kotlin/androidx/navigation/testing/TestNavigatorState.android.kt
- A
navigation/navigation-testing/src/androidUnitTest/kotlin/androidx/navigation/testing/RobolectricTest.android.kt
- M
navigation/navigation-testing/src/androidUnitTest/kotlin/androidx/navigation/testing/TestSavedStateHandleFactory.kt
- A
navigation/navigation-testing/src/commonMain/kotlin/androidx/navigation/testing/SavedStateHandleFactory.kt
- M
navigation/navigation-testing/src/commonMain/kotlin/androidx/navigation/testing/TestNavigatorProvider.kt
- D
navigation/navigation-testing/src/main/AndroidManifest.xml
- D
navigation/navigation-testing/src/main/java/androidx/navigation/testing/SavedStateHandleFactory.kt
Hash: 31ae4c7ebb13918db0e022b19246b7a47755ac65
Date: Fri Mar 07 09:11:14 2025
cl...@google.com <cl...@google.com> #3
Project: platform/frameworks/support
Branch: androidx-main
Author: Jeremy Woods <
Link:
Implement jvmTest for navigation-testing
Expand for full commit details
Implement jvmTest for navigation-testing
Adding a copy of TestSavedStateHandleFactory to jvmCommonTest to ensure
that is runs on all nonAndroid platforms.
The `nullLiteralArgument` and `emptyStringArgument` tests are expected
to fail as they require the encoding and decoding the types which is
behavior only supported on the jetbrains fork.
Test: added tests
Bug: 398265336
Change-Id: I4c1dcfb697d6e9e16995b249b9a8351bd925e0f3
Files:
- M
navigation/navigation-testing/build.gradle
- A
navigation/navigation-testing/src/jvmCommonTest/kotlin/androidx/navigation/testing/TestSavedStateHandleFactory.kt
Hash: 139d2423c7625f19ececc94b2df5bfde24e2cf95
Date: Fri Mar 14 23:48:06 2025
ap...@google.com <ap...@google.com> #4
Project: platform/frameworks/support
Branch: androidx-main
commit 62f4fb24bcfb6c77684dad3a33d4a70b22fdf5aa
Author: Clara Fok <clarafok@google.com>
Date: Wed Jun 14 13:15:57 2023
Add screenshot test for NavHost zIndex
Test: ./gradlew navigation:navigation-compose:cC
Bug: 285153947
Change-Id: Id810649107018fcc480cc26a33171a2dded5bdb0
M navigation/navigation-compose/build.gradle
M navigation/navigation-compose/src/androidTest/java/androidx/navigation/compose/NavHostTest.kt
https://android-review.googlesource.com/2627217
Branch: androidx-main
commit 62f4fb24bcfb6c77684dad3a33d4a70b22fdf5aa
Author: Clara Fok <clarafok@google.com>
Date: Wed Jun 14 13:15:57 2023
Add screenshot test for NavHost zIndex
Test: ./gradlew navigation:navigation-compose:cC
Bug: 285153947
Change-Id: Id810649107018fcc480cc26a33171a2dded5bdb0
M navigation/navigation-compose/build.gradle
M navigation/navigation-compose/src/androidTest/java/androidx/navigation/compose/NavHostTest.kt
Description
Devices/Android versions reproduced on: API 33
Animation is broken when navigating between two NavGraphs while using the NavOption popUpTo(0) { inclusive = true }. Not a problem when val zIndex = composeNavigator.backStack.value.size.toFloat() as NavHost returns increasing indices for subsequent screens.
However, when popping all back stack entries, the index for the next screen is reset to 1.0 at some point resulting in the broken animation. Attached video of broken animation.
Repro code
```
package com.example.myapplication
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.*
import androidx.compose.animation.core.FiniteAnimationSpec
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.navigation
import com.example.myapplication.ui.theme.MyApplicationTheme
import com.google.accompanist.navigation.animation.AnimatedNavHost
import com.google.accompanist.navigation.animation.composable
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
import org.w3c.dom.Text
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApplicationTheme {
Surface {
MyNavHost()
}
}
}
}
}
val SUBGRAPH1 = "Subgraph1"
val FIRSTVIEW1 = "FirstView1"
val SECONDVIEW1 = "SecondView1"
val SUBGRAPH2 = "Subgraph2"
val FIRSTVIEW2 = "FirstView2"
val SECONDVIEW2 = "SecondView2"
@OptIn(ExperimentalAnimationApi::class)
@Composable
fun MyNavHost() {
val navController = rememberAnimatedNavController()
val durationMillis = 1500
val offsetAnimationSpec: FiniteAnimationSpec<IntOffset> = remember { tween(durationMillis) }
val floatAnimationSpec: FiniteAnimationSpec<Float> = remember { tween(durationMillis) }
// the start destination is always the welcome screen so we can popToRoot at any time
// only when a user is set, we navigate to the map directly without animation
AnimatedNavHost(
navController = navController,
startDestination = SUBGRAPH1,
enterTransition = {
slideInHorizontally(
initialOffsetX = { it / 2 },
animationSpec = offsetAnimationSpec
) + fadeIn(animationSpec = floatAnimationSpec)
},
exitTransition = {
slideOutHorizontally(
targetOffsetX = { -it / 2 },
animationSpec = offsetAnimationSpec
)
},
popEnterTransition = {
slideInHorizontally(
initialOffsetX = { -it / 2 },
animationSpec = offsetAnimationSpec
)
},
popExitTransition = {
slideOutHorizontally(
targetOffsetX = { it / 2 },
animationSpec = offsetAnimationSpec
) + fadeOut(animationSpec = floatAnimationSpec)
},
modifier = Modifier.fillMaxSize()
) {
navGraph1(navController)
navGraph2(navController)
}
}
@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.navGraph1(
navController: NavController
) {
navigation(
startDestination = FIRSTVIEW1,
route = SUBGRAPH1
) {
composable(FIRSTVIEW1) {
PlaceholderComposable(
text = FIRSTVIEW1,
color = Color.Green,
onNext = { navController.navigate(SECONDVIEW1) }
)
}
composable(SECONDVIEW1) {
PlaceholderComposable(
text = SECONDVIEW1,
color = Color.Red,
onNext = { navController.navigate(SUBGRAPH2) },
onPrevious = { navController.navigateUp() }
)
}
}
}
@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.navGraph2(
navController: NavController
) {
navigation(
startDestination = FIRSTVIEW2,
route = SUBGRAPH2
) {
composable(FIRSTVIEW2) {
PlaceholderComposable(
text = FIRSTVIEW2,
color = Color.Yellow,
onNext = {
navController.navigate(SECONDVIEW2) {
popUpTo(0) { inclusive = true }
}
},
onPrevious = { navController.navigateUp() }
)
}
composable(SECONDVIEW2) {
PlaceholderComposable(
text = SECONDVIEW2,
color = Color.Blue,
onNext = {
navController.navigate(SUBGRAPH1) {
popUpTo(0) { inclusive = true }
}
}
)
}
}
}
@Composable
fun PlaceholderComposable(
text: String,
color: Color,
onNext: (() -> Unit)? = null,
onPrevious: (() -> Unit)? = null
) {
Column(
modifier = Modifier
.fillMaxSize()
.background(color),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(text = text)
Row {
onPrevious?.let { callback ->
Button(
onClick = { callback() },
modifier = Modifier.padding(8.dp)
) {
Text(text = "Previous")
}
}
onNext?.let { callback ->
Button(
onClick = { callback() },
modifier = Modifier.padding(8.dp)
) {
Text(text = "Next")
}
}
}
}
}
```
Steps to repro
1. click "next"
2. click "previous"
3. click "next"
4. click "next"
5. click "next"