9

I've created a fairly classic collapsing image layout in Jetpack compose, where I have an image at the top of the screen which parallax scrolls away and at a certain point I change the toolbar background from transparent to primarySurface. This is all working quite nicely.

I now want to have a pager of images at the top instead of a single one but the vertical scroll is consuming all the touches in the top part of the screen. I've tried adding a NestedScrollConnection but I still only seem to get the preScroll delta on one axis. I apparently can't even add icons within this area to do a manual pager scroll without the click being consumed. As soon as I remove the verticalScroll from my Column I'm able to get the horizontal scroll events for the pager.

I'm using Compose 1.0.2 and Accompanist 0.18 pager and inset libraries.

This is a gist of the existing code that I want to add a pager into. How can I get both the pager and the vertical scroll to work?

val scrollState = rememberScrollState()
Box {
    val imageHeight =
        if (LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE) 180.dp else 300.dp
    Box {
        // I want to insert a horizontal pager here
        HeaderImage(
            scrollPosition = scrollState.value,
            info = item.heroImages.first(),
            imageHeight = imageHeight
        )
    }
    val appBarHeight = with(LocalDensity.current) { 56.dp.toPx() }
    val scrollHeight = with(LocalDensity.current) { imageHeight.toPx() - appBarHeight }

    Column(
        Modifier
            .verticalScroll(scrollState)
            .padding(top = imageHeight)
            .fillMaxSize()
    ) { ... }
    TopAppBar( ... )

Here is a github repository where I've tried to show a simple example of the issue. I either end up with a horizontal pager that can't be scrolled vertically or where the main scroll layout also consumes the horizontal scrolls that the pager requires in order to work.

https://github.com/barry-irvine/scroll_issue

Barry Irvine
  • 13,858
  • 3
  • 25
  • 36
  • This is still a problem with Compose 1.2.0-beta01 and Accompanist 0.24.8-beta – Barry Irvine May 18 '22 at 13:59
  • I didn't get it, should the pager view scroll horizontally in sync with `verticalScroll` scrolling vertically? or should it be part of vertical scroll? – Phil Dukhov May 18 '22 at 16:41
  • At the moment the vertical scroll consumes all the scroll events (including horizontal) so there is nothing for the pager to get. It just never receives the horizontal scrolls. – Barry Irvine May 18 '22 at 19:42
  • Hi Pylyp, I've created a simple example so that you can hopefully understand the issue. https://github.com/barry-irvine/scroll_issue – Barry Irvine May 19 '22 at 11:25
  • What's wrong with doing it like [this](https://gist.github.com/PhilipDukhov/e9367de9dce63e10bd80f5123654bc1a)? As for me, it works fine - you can scroll both left/right and up/down - the direction is selected at the first drag, which I think is convenient. – Phil Dukhov May 19 '22 at 19:09

3 Answers3

2

There is no problem with placing a horizontal scroll view inside a vertical one: scrolling will work without problems, and the current scrolling direction of the gesture will be chosen based on the first dragged pixels direction.

Column(
    Modifier
        .verticalScroll(scrollState)
) {
    HorizontalPager(/*...*/)
    OtherScrollableContent(/*...*/)
}
Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220
  • 1
    I had a feeling OP wanted to activate the horizontally scrolling element simultaneously with the vertically scrolling element. As far as I know, this is not possible without basically re-implementing the Compose scrolling mechanism ([issue](https://issuetracker.google.com/issues/232652204)) – Maarten May 23 '22 at 14:39
  • Please upvote the google [issue](https://issuetracker.google.com/issues/232652204) mentioned above to get real diagonal scroll. – Morten Holmgaard Feb 02 '23 at 19:14
2

I just created a library to do this. You can scroll in both direction simultaneously with this library. However, it currently lacks a bounce effect and some other features found in the official scrolling modifier.

A simple example:

val scrollState = rememberFreeScrollState()
Column(
    modifier = Modifier
        .fillMaxSize()
        .freeScroll(state = freeScrollState)
) {
    // Content ...
}
0

Modifying the previous answer, it's possible to scroll in both ways (but not possible to do diagonal scrolling):

val scrollStateHorizontal = rememberScrollState()
val scrollStateVertical = rememberScrollState()

Box(
    modifier = Modifier
        .horizontalScroll(scrollStateHorizontal)
        .verticalScroll(scrollStateVertical)
) {
//Content here
}
Psijic
  • 743
  • 7
  • 20