Skip to content

Instantly share code, notes, and snippets.

@arcadefire
Created September 12, 2021 12:50
Show Gist options
  • Select an option

  • Save arcadefire/7fe138c0ded1a36bee6dd57acdfa3d18 to your computer and use it in GitHub Desktop.

Select an option

Save arcadefire/7fe138c0ded1a36bee6dd57acdfa3d18 to your computer and use it in GitHub Desktop.

Revisions

  1. Angelo Marchesin created this gist Sep 12, 2021.
    100 changes: 100 additions & 0 deletions bottomsheet.kt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,100 @@
    enum class States {
    EXPANDED,
    COLLAPSED
    }

    @ExperimentalMaterialApi
    @Composable
    fun FullHeightBottomSheet(
    header: @Composable () -> Unit,
    body: @Composable () -> Unit
    ) {
    val swipeableState = rememberSwipeableState(initialValue = States.EXPANDED)
    val scrollState = rememberScrollState()

    BoxWithConstraints {
    val constraintsScope = this
    val maxHeight = with(LocalDensity.current) {
    constraintsScope.maxHeight.toPx()
    }

    val connection = remember {
    object : NestedScrollConnection {

    override fun onPreScroll(
    available: Offset,
    source: NestedScrollSource
    ): Offset {
    val delta = available.y
    return if (delta < 0) {
    swipeableState.performDrag(delta).toOffset()
    } else {
    Offset.Zero
    }
    }

    override fun onPostScroll(
    consumed: Offset,
    available: Offset,
    source: NestedScrollSource
    ): Offset {
    val delta = available.y
    return swipeableState.performDrag(delta).toOffset()
    }

    override suspend fun onPreFling(available: Velocity): Velocity {
    return if (available.y < 0 && scrollState.value == 0) {
    swipeableState.performFling(available.y)
    available
    } else {
    Velocity.Zero
    }
    }

    override suspend fun onPostFling(
    consumed: Velocity,
    available: Velocity
    ): Velocity {
    swipeableState.performFling(velocity = available.y)
    return super.onPostFling(consumed, available)
    }

    private fun Float.toOffset() = Offset(0f, this)
    }
    }

    Box(
    Modifier
    .swipeable(
    state = swipeableState,
    orientation = Orientation.Vertical,
    anchors = mapOf(
    0f to States.EXPANDED,
    maxHeight to States.COLLAPSED,
    )
    )
    .nestedScroll(connection)
    .offset {
    IntOffset(
    0,
    swipeableState.offset.value.roundToInt()
    )
    }
    ) {
    Column(
    Modifier
    .fillMaxHeight()
    .background(Color.White)
    ) {
    header()
    Box(
    Modifier
    .fillMaxWidth()
    .verticalScroll(scrollState)
    ) {
    body()
    }
    }
    }
    }
    }