Hey there, I'm trying to migrate an existing Andro...
# compose
d
Hey there, I'm trying to migrate an existing Android View/XML based screen into Compose. Unfortunately, it involves nested vertically scrolling components, which worked seamlessly and flawlessly, but getting the expected "nested vertical scrolling" issues in Compose. Wondering what, if anything, I can do about this, other than a UI redesign 🧵
Here is the screen wireframe. The whole screen (minus the toolbar) is supposed to scroll vertically. As the screen scrolls up, the Header title morphs into the Toolbar title, as the whole header section scrolls out of view. Below the Header is the body, consisting of a 2 Tabs. Each tab's contents consumes the remainder of the screen space below the tab strip. Tab 1 has a LazyVerticalGrid of a potentially large number of items. Tab 2 is similar, but a LazyColumn instead of Grid. Users should be able to swipe horizontally to be able to switch between tabs. I've managed to code things such that Compose does not complain about these nested items with the following composable heirarchy: • Scaffold ◦ topBar: ▪︎ TopAppBar ◦ contents: ▪︎ LazyColumn • Header • TabRow • HorizontalPager ◦ Tab1 contents ◦ Tab2 contents It kind of works, except that the scrolling behavior is different. Previously, initiating a scroll by touching anywhere in Scaffold contents would scroll everything, even if you the scroll gesture started by tapping in one of the Lazy components contained inside the HorizontalPager. i.e. initiating a vertical scroll with a tap and upward gesture starting from Tab1/2 contents would first scroll the Header out of view, and then scroll the items inside the LazyGrid/Columns. It "just worked", as if everything was a single scrolling entity. Now, perhaps expectedly, the scrolling behavior is entirely dependent on where you tap to initialize the scroll. If you initiate the scroll by tapping inside of the HorizontalPager, the header will remain fixed, and the only items that scroll are the items inside the LazyGrid/Column. If you initiate the scroll by touching down on the header, everything scrolls kind of as expected, until the header is out of view. It just feels odd. Is there anything I can do to achieve the same behavior as before?
d
Yeah this is a hard one. I am trying to good articles on this topic.
a
> If you initiate the scroll by touching down on the header This is TopAppBar's (internal) draggable modifier that's doing it. Could you show us some minimal code? Are you supplying
scrollBehavior
to the TopAppBar, and where are applying
Modifier.nestedScroll(scrollBehavior)
? I think either Scaffold or LazyColumn would work, but former would be better.
Oh and it would help knowing if this is M3 or M2, as I believe it's slightly different
d
The Scaffold is Material3, no other Material components. The Header is part of the
Scaffold's
Content block, not it's TopAppBar. I'm not talking about touching down on the
TopAppBar
, but the behavior being different depending on which section of content you touch down on. If you touch down anywhere in the outer, top level,
LazyColumn
, the scrolling behavior is different than if you touch down on the
LazyGrid/Column
contained inside the
HorizontalPager
. I'm not adding
scrollBehavior
or
nestedScroll
anywhere. The way I was able to silence the "Vertically scrollable component was measured with an infinity maximum height constraints, which is disallowed" barrier was by adding
fillParentMaxHeight
to the
HorizontalPager
. Where are you suggesting that I should be applying the nestedScroll behavior?
To clarify the differences between the XML/View and Compose behavior: • XML/View: Initiating a scroll by tapping on one of the inner columns/grids (inside the HorizontalPager) will start scrolling the entire screen immediately (i.e. the header starts scrolling up immediately and everything scrolls up with it). This feels pretty natural from a UX POV. • Compose: Initiating a scroll by tapping on one of the inner columns/grids (inside the HorizontalPager) will first scroll scroll only the inner column/grid until it is exhausted. Once the inner scrolling has reached the end, the outer/header will start scrolling.
> This is TopAppBar's (internal) draggable modifier that's doing it. Could you show us some minimal code? Are you supplying
scrollBehavior
to the TopAppBar, and where are applying
Modifier.nestedScroll(scrollBehavior)
? I think either Scaffold or LazyColumn would work, but former would be better. The TopAppBar has no scroll modifier applied to it. Nothing has any
nestedScroll
applied to it. No scrolling related modifiers are passed to any components. The Header is not part of the TopAppBar. It sits in the content part of the scaffold, not in the TopAppBar. This issue exists if you start scrolling on the Header and don't engage with the TopAppBar at all