Bradleycorn
04/12/2024, 7:48 PMNavHost
composable with no special handling for transistions (it uses the default enter/exit and pop transistions).
What I’m seeing, is that when I navigate in one case, the new destination slides in diagonally from the top left??? I’m not sure where that’s coming from or what is causing it.
Here’s a video that shows the issue. You can see the diagonal animation at the 3 second mark. After that, there are a few button clicks that do additional navigations (using the exact same methods) that work correctly (they use the default fading between destinations).
Has anyone else seen this weird “diagonal animation” when navigating?Stylianos Gakis
04/12/2024, 7:56 PMfillMaxSize()
on the first contained composable inside your composable() { Box(Modifier.fillMaxSize()) { screen content… } }
Bradleycorn
04/12/2024, 7:57 PM.fillMaxSize()
on all of my “screen” contentStylianos Gakis
04/12/2024, 7:57 PMStylianos Gakis
04/12/2024, 7:57 PMI do haveShow some codeon all of my “screen” content.fillMaxSize()
Stylianos Gakis
04/12/2024, 7:58 PMBradleycorn
04/12/2024, 7:59 PMStylianos Gakis
04/12/2024, 8:02 PMBradleycorn
04/12/2024, 8:05 PMScaffold(modifier = Modifier.fillMaxSize()) {
MyNavHost(appState.navController, onLoginComplete = { appState.isLoggedIn = true }, modifier = Modifier.fillMaxSize().padding(it))
}
And now that initial view animates in diagonally from the bottom rightStylianos Gakis
04/12/2024, 8:07 PMBradleycorn
04/12/2024, 8:08 PMStylianos Gakis
04/12/2024, 8:10 PMBradleycorn
04/12/2024, 8:12 PMBradleycorn
04/12/2024, 8:15 PMBradleycorn
04/12/2024, 8:15 PM/**
* MyAppState handles the primary State for the application as a whole
*/
class MyAppState(
val navController: NavHostController
) {
/**
* isLoggedIn keeps track of the user login state.
*
* In a real app, this value could change at any time and
* as a result of many different things (such as a session timing out, clicking a logout button, etc).
*/
var isLoggedIn by mutableStateOf(false)
}
@Composable
fun rememberAppState(navController: NavHostController = rememberNavController()): MyAppState {
return remember { MyAppState(navController) }
}
@Composable
fun MyApp(appState: MyAppState = rememberAppState()) {
/**
* The user cannot access the home screen unless/until they are logged in.
* In addition, if/when their login state changes and they are no longer logged in,
* then we want to leave the home screen and show the login screen.
*/
LaunchedEffect(appState.isLoggedIn) {
if (!appState.isLoggedIn) {
//THIS NAVIGATION IS THE ONE THAT ANIMATES WEIRD
appState.navController.navigateToLogin()
}
}
Scaffold(modifier = Modifier.fillMaxSize()) {
NavHost(
navController = appState.navController,
startDestination = "home",
modifier = Modifier
.fillMaxSize()
.padding(it)
) {
composable(route = "home") {
Surface(modifier = Modifier.fillMaxSize()) {
Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center) {
Text("Welcome Logged in user!!")
Spacer(modifier = Modifier.height(24.dp))
Button(onClick = { appState.navController.navigateToLogin() }) {
Text("Logout")
}
}
}
}
composable(route = "login") {
Surface(modifier = Modifier.fillMaxSize()) {
Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center) {
Text("Click the button Below to Login")
Spacer(modifier = Modifier.height(24.dp))
Button(onClick = {
appState.isLoggedIn = true
appState.navController.navigateToHome()
}) {
Text("Login")
}
}
}
}
}
}
}
/**
* Navigate to login.
* Pops all destinations from the backstack, making login
* the root destination.
*/
fun NavHostController.navigateToLogin() {
val rootDestination = this.graph.findStartDestination().id
navigate(
route = "login",
navOptions = navOptions {
popUpTo(rootDestination) { inclusive = true }
}
)
}
/**
* Navigate to home.
* Pops all destinations from the backstack, making home
* the root destination.
*/
fun NavHostController.navigateToHome() {
val rootDestination = this.graph.findStartDestination().id
navigate(
route = "home",
navOptions = navOptions {
popUpTo(rootDestination) { inclusive = true }
}
)
}
Stylianos Gakis
04/12/2024, 9:09 PMStylianos Gakis
04/12/2024, 9:10 PMNavHost()
call and see what that does for youMahmoo
04/12/2024, 10:00 PMBradleycorn
04/13/2024, 3:27 PMLaunchedEffect
after the NavHost
doesn’t change anything. I can put a delay(xxx)
in the LaunchedEffect
and that does “fix” it, but that’s not great for obvious reasons.
I mainly posted the issue here to get a sense of whether this is expected behavior, or an actual defect (like those that @Mahmoo pointed out). I get that what I’m doing (navigating to a new destination immediately) is maybe a bit unorthodox so maybe I shouldn’t be surprised by the weird animation. At the same time, it seems odd that there is any “sliding” animation of content at all, when the NavHost is defined without any sliding transitions.
If it is indeed a defect, I can file it on the issue tracker.
If it’s expected behavior, I think I can mitigate it, by dynamically calculating the startDestination
to pass to the NavHost
based on the isLoggedIn
state, and also adding some additional logic to my navigateToLogin()
extension function so that it doesn’t pop the start destination if that destination is already the login destination.Stylianos Gakis
04/13/2024, 4:19 PM