ModalBottomSheetLayout is jumping on flinging in Compose 1.4.0 and above

adm*_*und 6 android bottom-sheet android-jetpack-compose

I searching for possibility for turning OFF this "jumping"

https://www.veed.io/view/0f7585b4-529f-4700-8dc2-15788164fa44

I don't see it on Compose version below 1.4.0. My code:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val scope = rememberCoroutineScope()
            val sheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden)
            ModalBottomSheetLayout(
                sheetState = sheetState,
                sheetContent = {
                    Text(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(200.dp),
                        text = "CONTENT"
                    )
                }
            ) {
                Button(onClick = { scope.launch { sheetState.show() } }) {
                    Text(text = "MODAL")
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

I searching for possibility for turning OFF this "jumping feature".

PS. looks like there is an issue for that already https://issuetracker.google.com/issues/285847707, but maybe someone has a workaround?

小智 0

在sheetContent中尝试这个代码Modifier.nestedScroll,不知道Google需要多长时间才能解决这个问题,所以我必须自己解决它,但是这没有任何EdgeEffect,滚动到边缘时似乎不太好。

package com.lalilu.component.extension

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.unit.Velocity
import kotlin.math.abs

class BottomSheetNestedScrollInterceptor : NestedScrollConnection {
    private var arrivedBoundarySource: NestedScrollSource? = null

    override fun onPreScroll(
        available: Offset,
        source: NestedScrollSource
    ): Offset {
        // Reset the state variable
        if (source == NestedScrollSource.Drag && arrivedBoundarySource == NestedScrollSource.Fling) {
            arrivedBoundarySource = null
        }

        return super.onPreScroll(available, source)
    }

    override fun onPostScroll(
        consumed: Offset,
        available: Offset,
        source: NestedScrollSource
    ): Offset {
        // The sub-layout can't consume completely,
        // which means that the boundary has been reached.
        if (arrivedBoundarySource == null && abs(available.y) > 0) {
            arrivedBoundarySource = source
        }

        // Decide whether to consume according to the sub-layout
        // consumption when reaching the boundary.
        if (arrivedBoundarySource == NestedScrollSource.Fling) {
            return available
        }

        return Offset.Zero
    }

    override suspend fun onPostFling(
        consumed: Velocity,
        available: Velocity
    ): Velocity {
        arrivedBoundarySource = null
        return super.onPostFling(consumed, available)
    }
}

@Composable
fun rememberBottomSheetNestedScrollInterceptor(): BottomSheetNestedScrollInterceptor {
    return remember { BottomSheetNestedScrollInterceptor() }
}
Run Code Online (Sandbox Code Playgroud)