How to detect up/down scroll for a Column with vertical scroll?

Viewed 1457

I have a column which has many items; based on the scroll, I want to show/hide the Floating action button, in case the scroll is down, hide it and in case the scroll is up, show it.

My code is working partially, but the scrolling is buggy. Below is the code. Need help.

 Column(
      Modifier
        .background(color = colorResource(id = R.color.background_color))
        .fillMaxWidth(1f)
        .verticalScroll(scrollState)
        .scrollable(
          orientation = Orientation.Vertical,
          state = rememberScrollableState {
            offset.value = it

              coroutineScope.launch {
                scrollState.scrollBy(-it)
              }

            it
          },
        )
    ) { // 10-20 items }

Based on the offset value (whether positive/negative), I am maintaining the visibility of FAB.

1 Answers

You can use the nestedScroll modifier.

Something like:

val fabHeight = 72.dp //FabSize+Padding
val fabHeightPx = with(LocalDensity.current) { fabHeight.roundToPx().toFloat() }
val fabOffsetHeightPx = remember { mutableStateOf(0f) }

val nestedScrollConnection = remember {
    object : NestedScrollConnection {
        override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {

            val delta = available.y
            val newOffset = fabOffsetHeightPx.value + delta
            fabOffsetHeightPx.value = newOffset.coerceIn(-fabHeightPx, 0f)

            return Offset.Zero
        }
    }
}

Since composable supports nested scrolling just apply it to the Scaffold:

Scaffold(
        Modifier.nestedScroll(nestedScrollConnection),
        scaffoldState = scaffoldState,
        //..

        floatingActionButton = {
            FloatingActionButton(
                modifier = Modifier
                    .offset { IntOffset(x = 0, y = -fabOffsetHeightPx.value.roundToInt()) },
                onClick = {}
            ) {
                Icon(Icons.Filled.Add,"")
            }
        },
        content = { innerPadding ->
            Column(
                Modifier
                    .fillMaxWidth(1f)
                    .verticalScroll(rememberScrollState())
            ) {
                //....your code
            }
        }
 )

It can work with a Column with verticalScroll and also with a LazyColumn.

enter image description here

Related