Jetpack Compose: Custom scroll where vertical scrolling should stop when a specific element reaches top of the screen

361 Views Asked by At

I am currently in the process of developing a feature within an Android application using Jetpack Compose. This feature is designed to provide customized scrolling functionality for an UI screen, specifically for vertical scrolling of the screen's content. The primary objective of this feature is to implement a distinct scrolling behavior: when a specific element (e.g., a Text view) is scrolled down and reaches the top of the screen, scrolling should come to a halt.

Users will have the flexibility to continue scrolling below this particular element, while the said element remains statically positioned at the top of the screen. However, when users initiate a scroll-up action (i.e., swipe down), the specific element will regain its dynamic scrolling behavior and return to its original position, allowing users to view the content that was positioned above it prior to scrolling.

I tried the below attached code to achieve the said scrolling feature but wasn't successful and not sure if this is the right approach i'm taking for implementing the same.

Current try:- "Used pointerInput, detectVerticalDragGestures, and verticalScroll modifiers to enable custom scrolling behavior. I think enabled = (scrollOffset == 0f) is not being triggered upon scrolling and so the enabled value is always true due to which it is just acting as a normal scroll. But still i'm confused if this is the right direction i'm thinking in.

@Composable
fun ScrollWithStopFeature() {
    var scrollOffset by remember { mutableStateOf(0f) }
    val maxScrollOffset = 200.dp // Adjust this value as needed

    Box(
        modifier = Modifier.fillMaxSize()
    ) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .background(Color.White)
                .padding(16.dp)
                .pointerInput(Unit) {
                    detectVerticalDragGestures { _, dragAmount ->
                        // Calculate the new scroll offset
                        val newScrollOffset = scrollOffset + dragAmount

                        // Ensure scrolling stops when the element reaches the top
                        scrollOffset = if (newScrollOffset < 0f) {
                            0f
                        } else if (newScrollOffset > maxScrollOffset.toPx()) {
                            maxScrollOffset.toPx()
                        } else {
                            newScrollOffset
                        }
                    }
                }
                .verticalScroll(enabled = (scrollOffset == 0f), state = rememberScrollState())
        ) {
            // Text element
            BasicTextField(
                value = "Random Text View",
                onValueChange = {},
                modifier = Modifier
                    .fillMaxWidth()
                    .background(Color.LightGray)
                    .padding(16.dp)
            )

            Text(
                text = "Scroll stops when this reaches top",
                modifier = Modifier
                    .fillMaxWidth()
                    .background(Color.Red)
                    .padding(16.dp)
            )

            Spacer(modifier = Modifier.height(16.dp))

            for (i in 1..50) {
                Text(text = "Item $i", modifier = Modifier.padding(16.dp))
            }
        }
    }
}
0

There are 0 best solutions below