Hi, has anyone ever managed to make the Horizontal...
# compose
f
Hi, has anyone ever managed to make the HorizontalPager scroll in only one direction, so forward only, I can’t get either pointerInput or pointerInteropFilter to correctly handle my gesture detection:
Copy code
// if you use detectDragGesture on the box, then the message is printed, however the event does not bubble up and the horizontalPager will not swipe
  // if you put the pointerInput onto the HorizontalPager, then the gesture is not detected and no message is printed
  HorizontalPager(state = pagerState) { page ->
        // Display each page with a different background color
        Box(
            modifier = Modifier
                .fillMaxSize()
                .background(colors[page])
                .pointerInput(Unit) {
                    detectDragGestures { _, _ ->
                        println("In Here")
                    }
               }
        ) {
        }
   }
   
// the other option is to use pointerInteropFilter 
// the problem with this is that when used with the horizontalPager it does not detect the ACTION_MOVE for horizontal scroll
 HorizontalPager(state = pagerState) { page ->
        Box(
            modifier = Modifier
                .fillMaxSize()
                .background(colors[page])
                .pointerInteropFilter { motionEvent ->
                    when (motionEvent.action) 
                        MotionEvent.ACTION_MOVE -> {
		                        // This is not detected for horizontal scroll
                            println("ACTION_MOVE")
                        }                    }
                    true
                }
        ) {
            Text("Hello")
        }
    }
If I can correctly detect a backward swipe then I should be able to set userScrollEnabled on the pager to disable the backward swipe.
In the end I found the solution for this, incase it ever helps anyone, the following is the complete solution:
Copy code
package com.locovoco.app.ui.feature

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.PointerEvent
import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.pointerInput

@Composable
fun TempScreen() {
    HorizontalPagerDemo()
}

@OptIn(ExperimentalFoundationApi::class, ExperimentalComposeUiApi::class)
@Composable
private fun HorizontalPagerDemo() {

    val colors1 = listOf(Color.Red, Color.Blue, Color.Yellow, Color.Cyan, Color.Magenta)
    val colors2 = listOf(Color.Magenta, Color.Cyan, Color.Yellow, Color.Blue, Color.Red)
    val colors3 = listOf(Color.Red, Color.Blue, Color.Yellow, Color.Cyan, Color.Magenta)
    val colors4 = listOf(Color.Magenta, Color.Cyan, Color.Yellow, Color.Blue, Color.Red)
    val colors5 = listOf(Color.Red, Color.Blue, Color.Yellow, Color.Cyan, Color.Magenta)
    val colors6 = listOf(Color.Magenta, Color.Cyan, Color.Yellow, Color.Blue, Color.Red)

    val colors = listOf(
        colors1, colors2, colors3, colors4, colors5, colors6
    )

    val pagerState = rememberPagerState(
        pageCount = {
            colors.size
        }
    )

    var userScrollEnabled by remember {
        mutableStateOf(true)
    }

    // this works aswell, with far less code
//    val userScrollEnabled by remember {
//        derivedStateOf {
//            pagerState.currentPageOffsetFraction >= 0
//        }
//    }

    HorizontalPager(
        state = pagerState,
        userScrollEnabled = userScrollEnabled,
        modifier = Modifier.pointerInput(Unit) {
            awaitEachGesture {
                awaitFirstDown(pass = PointerEventPass.Initial)

                do {
                    val event: PointerEvent = awaitPointerEvent(
                        pass = PointerEventPass.Initial
                    )

                    event.changes.forEach {
                        val diffX = it.position.x - it.previousPosition.x

                        if (diffX > 0) {
                            userScrollEnabled = false
                        } else {
                            userScrollEnabled = true
                        }
                    }

                } while (event.changes.any { it.pressed })
            }
        }
    ) { horizontalPage ->

        LazyColumn(modifier = Modifier) {
            items(colors[horizontalPage].size) { verticalPage ->

                Box(
                    modifier = Modifier
                        .fillMaxSize()
                        .fillParentMaxHeight()
                        .background(colors[horizontalPage][verticalPage])
                ) {
                }
            }
        }
    }
}
This was answered on stackoverflow at https://stackoverflow.com/questions/78806535/how-do-i-make-jetpack-compose-horizontalpager-swipe-forward-only-disable-backwa#comment138[…]5_78806535
129 Views