Skip to content

Instantly share code, notes, and snippets.

@jershell
Created February 23, 2022 08:24
Show Gist options
  • Save jershell/b6df121a9738bf0a8a4b98b7032e44b9 to your computer and use it in GitHub Desktop.
Save jershell/b6df121a9738bf0a8a4b98b7032e44b9 to your computer and use it in GitHub Desktop.
compose swipe to remove
package com.github.gismenu.ui.components
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.animateIntAsState
import androidx.compose.foundation.gestures.detectHorizontalDragGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.unit.IntOffset
import kotlin.math.abs
import kotlin.math.roundToInt
enum class SwipeState {
ExpandedToLeft, ExpandedToRight, Collapsed
}
@Composable
fun SwipeToRemove(
modifier: Modifier = Modifier,
onRemove: () -> Unit = {},
onChangedOpenPart: (percent: Int, offsetX: Int) -> Unit = { _, _ -> },
behindContent: @Composable () -> Unit = {},
content: @Composable () -> Unit = {}
) {
val hOffset = remember { mutableStateOf(0) }
val h = remember { mutableStateOf(0) }
var state by remember { mutableStateOf(SwipeState.Collapsed) }
var useHandleOffset by remember { mutableStateOf(false) }
val offsetAnimation = animateIntAsState(
when (state) {
SwipeState.ExpandedToRight -> {
h.value
}
SwipeState.ExpandedToLeft -> {
-h.value
}
SwipeState.Collapsed -> hOffset.value
},
finishedListener = {
when (state) {
SwipeState.ExpandedToRight -> {
onRemove()
}
SwipeState.ExpandedToLeft -> {
onRemove()
}
SwipeState.Collapsed -> {}
}
}
)
Box(
modifier = modifier
.onGloballyPositioned {
h.value = it.size.width
}
.animateContentSize()
.pointerInput(Unit) {
detectHorizontalDragGestures(
onDragStart = {
useHandleOffset = true
},
onDragEnd = {
// anim.animateTo()
useHandleOffset = false
println("hOffset.value = ${hOffset.value}")
val p = (abs(hOffset.value) * 100) / h.value
state = if (p > 25) {
if (hOffset.value > 0) {
SwipeState.ExpandedToRight
} else {
SwipeState.ExpandedToLeft
}
} else {
hOffset.value = 0
SwipeState.Collapsed
}
},
onHorizontalDrag = { change, dragAmount ->
hOffset.value = hOffset.value + dragAmount.roundToInt()
val p = (abs(hOffset.value) * 100) / h.value
onChangedOpenPart(p, hOffset.value)
}
)
},
content = {
Box(Modifier.fillMaxSize()) {
behindContent()
}
Box(
Modifier
.fillMaxSize()
.offset {
if (useHandleOffset) {
IntOffset(x = hOffset.value, y = 0)
} else {
IntOffset(x = offsetAnimation.value, y = 0)
}
}) {
content()
}
}
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment