-
-
Save bmc08gt/f130c78580ccfb269795e74bcef96aa6 to your computer and use it in GitHub Desktop.
| import androidx.animation.IntToVectorConverter | |
| import androidx.animation.tween | |
| import androidx.compose.Composable | |
| import androidx.compose.mutableStateOf | |
| import androidx.compose.remember | |
| import androidx.ui.animation.animatedFloat | |
| import androidx.ui.animation.animatedValue | |
| import androidx.ui.core.* | |
| import androidx.ui.core.gesture.scrollorientationlocking.Orientation | |
| import androidx.ui.foundation.animation.FlingConfig | |
| import androidx.ui.foundation.animation.fling | |
| import androidx.ui.foundation.gestures.draggable | |
| import kotlin.math.absoluteValue | |
| import kotlin.math.roundToInt | |
| /** | |
| * [Modifier] enabling swipe to delete functionality on a Composable view. | |
| * | |
| * NOTE: <b>MUST</b> be added prior to padding modifiers to ensure that the collapse animation | |
| * will run to remove all available space. | |
| */ | |
| @Composable | |
| fun Modifier.swipeToDelete( | |
| constraints: Constraints, | |
| threshold: Float = .8f, | |
| swipeDirection: LayoutDirection? = null, | |
| onDelete: () -> Unit | |
| ): Modifier { | |
| val width = constraints.maxWidth | |
| val draggable = remember { mutableStateOf(true) } | |
| val deleted = remember { mutableStateOf(false) } | |
| val positionOffset = animatedFloat(0f) | |
| val collapse = remember { mutableStateOf(0) } | |
| val animatedCollapse = animatedValue(initVal = 0, converter = IntToVectorConverter) | |
| return this + Modifier.draggable( | |
| enabled = draggable.value, | |
| orientation = Orientation.Horizontal, | |
| onDrag = { delta -> | |
| when (swipeDirection) { | |
| LayoutDirection.Ltr -> positionOffset.snapTo((positionOffset.value + delta).coerceAtLeast(0f)) | |
| LayoutDirection.Rtl -> positionOffset.snapTo((positionOffset.value + delta).coerceAtMost(0f)) | |
| else -> positionOffset.snapTo(positionOffset.value + delta) | |
| } | |
| }, | |
| onDragStopped = { velocity -> | |
| val config = FlingConfig(anchors = listOf(-width.toFloat(), 0f, width.toFloat())) | |
| if (positionOffset.value.absoluteValue >= threshold) { | |
| positionOffset.fling(velocity, config) { _, endValue, _ -> | |
| if (endValue != 0f) { | |
| animatedCollapse.snapTo(collapse.value) | |
| animatedCollapse.animateTo(0, onEnd = { _, _ -> | |
| deleted.value = true | |
| draggable.value = false | |
| onDelete() | |
| }, anim = tween(500)) | |
| } | |
| } | |
| } else { | |
| draggable.value = true | |
| } | |
| } | |
| ) + object : LayoutModifier { | |
| override fun MeasureScope.measure( | |
| measurable: Measurable, | |
| constraints: Constraints, | |
| layoutDirection: LayoutDirection | |
| ): MeasureScope.MeasureResult { | |
| val child = measurable.measure(constraints) | |
| positionOffset.setBounds(-width.toFloat(), width.toFloat()) | |
| collapse.value = child.height | |
| val placeHeight = if (animatedCollapse.isRunning || deleted.value) { | |
| animatedCollapse.value | |
| } else { | |
| child.height | |
| } | |
| return layout(child.width, placeHeight) { | |
| child.place(positionOffset.value.roundToInt(), 0) | |
| } | |
| } | |
| } | |
| } |
Hi, I'm trying to use this to implement swipe to delete in a LazyColumn item.
Where can I get the constraints for this modifier?
I tried to simply use Constraints but since in this case constraints.maxWidth is Constraints.Infinity, onDelete() is not trigger at all.
Setting a fix number using Constraints.fixedWidth() works but I want to make it fill the available width.
Hi, I'm trying to use this to implement swipe to delete in a
LazyColumnitem.
Where can I get theconstraintsfor this modifier?
I tried to simply useConstraintsbut since in this caseconstraints.maxWidthisConstraints.Infinity,onDelete()is not trigger at all.
Setting a fix number usingConstraints.fixedWidth()works but I want to make it fill the available width.
I would definitely try out https://gist.github.com/bmc08gt/fca95db3bf9fcf255d76f03ec10ea3f9. This gist was created before there was a first class modifier for this available and that one has better support.
Thank you. Using SwipeToDismiss is definitely easier.
@bmc08gt this example is amazing!