I am having a hard time understanding why my anima...
# compose
s
I am having a hard time understanding why my animation on a NavHost as the new screen is coming in is sliding as it is. I am going to attach a video just so that I can show you what I am experiencing, maybe someone has experienced the same thing.
The borders on the screen coming in are showing that the right amount of space is in fact give to the incoming screen from the beginning, only that there’s something that is clipping it vertically, as the screen is coming in and the bottom navigation bar is animating out. The structure of this is that there’s an outer column, which contains the NavHost, and then the bottom bar which is wrapped in an AnimatedContent (The one which is an extension on ColumnScope). To test this, the bottom nav bar is just animating in and out every 1 second Notice how it does not happen on the first navigation, as the first one does not happen in parallel with the bottom nav bar animating out. But I time the other navigations so that it happens simultaneously and I get this weird effect.
Basically this frame shows the issue if you look at the top and the bottom of it.
For the NavHost, even if I use
EnterTransition.None
and
ExitTransition.None
for the transitions I get the same thing, so it’s not my transition either 😅 I really can’t figure out what is it that makes it animate like that, while the screen is laid out properly and the borders show where they should be 🤔
I made this issue https://issuetracker.google.com/issues/285653481 and this repro project https://github.com/StylianosGakis/repro-animated-content-clipping I still don’t understand if this is a bug or I am doing something wrong. But a NavHost with enter/exit transitions of EnterTransition.None/ExitTransition.None where the layout is like this
Copy code
Column {
  NavHost(Modifier.weight(1f)) {...}
  val height by animateDpAsState(if (showBottomNav) 120.dp else 0.dp)
  BottomNavBar(Modifier.height(height))
}
I don’t think I should be experiencing what I am experiencing here 🤔
d
I think I've seen this same problem too. Try swapping the column with a Box just to see if that fixes this issue (even if that will cause other problems).
s
Yeah then I am not going to be getting the experience that I am going for, which is to have the bottom nav take as much space as it needs, and the content to take the rest. I could maybe achieve the same by using subcomposition, and measuring the bottom nav bar first, and passing that height as padding values to the other content, or something weird like that. But I’d like to avoid doing that if possible, especially considering I also got a NavRail in this screen when the WindowSizeClass width is anything but the smallest value, which would make this even more work 😅 I am hoping someone sees the issue I’ve made from google and can either tell me: • Idk what this is. In which situation either I take the L and accept this or do something like what you suggest • Oh this is because you did X instead of Y. In which situation I follow that advice 😄
d
Is the box really that bad? I don't have navigation rail support so can't picture it in my head atm. I don't think switching to Box is that bad (excl navigation rail): Your bottom nav already has a fixed height. Your content would be as big as the box and the bottom nav with its fixed height will sit on top of all that.
I don't know if you depend on other Column behaviour but as mentioned I had the same problem and had to make the switch
s
Yeah, but as the bottom navigation bar is animating out, how would you make the content on top to react to that change if they’re just in a box? While still making sure that the content above doesn’t have things hidden behind the bottom bar of course.
d
How should the content on top react? It's sitting on top so perhaps it shouldn't really react any more than apply conditional padding equal to your bottom nav height
s
Yeah, so that’d be done though a SubComposeLayout I suppose right? Since I want to use the result of one composable and pass it to another composable, just like
Scaffold
does,
d
Not in the basic case.
Copy code
Box {
  NavHost(addBottomNavPadding = showBottomNav) // pseudo code
  AnimatedVisibility(showBottomNav) {
    BottomNav()
  }
}
What do you need to get out of a SubComposeLayout?
s
Hmm, specifically with my implementation, I can’t really pass some inner padding to my content. The content is one NavHost, which doesn’t take in some sort of
contentPadding
. So if I apply that padding to the NavHost itself then as the bottom bar animates out, I need to also animate that padding so that it feels like they’re attached to each other, while in reality all they’re doing is being in the same box, only with “matching” height/bottom padding between them. While all I needed in reality is a column where the NavHost takes the space that the bottom bar does not take. And if I make the NavHost take up the entire height anyway, there’s no way to pass to every single item it may have inside of it the bottom height so that it will use it to pad itself. It would mean every single screen in my entire app needs to do that. Not sure if I am thinking about this with a wrong approach though, I might come up with a better idea the more I think about it. Or maybe even unblock myself from understanding what you really mean if I am still misunderstanding you.
d
Maybe take a step back from the height and think how it could work with just a "isBottomNavShown" boolean. You could use a composition local to make that bool available to the tree downwards. Then you could create a Modifier that reads that composition local and applies bottom padding. Afterwards apply the new modifier to the Screen level composable and pad however you want. You'd know the padding value because it should be equal to a constant = your bottom nav height.