Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Option (swipeMaxDistance) to limit swiping distance #26

Open
wants to merge 1 commit into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package me.saket.swipe

import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.EaseIn
import androidx.compose.animation.core.Easing
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
Expand Down Expand Up @@ -35,6 +37,12 @@ import kotlin.math.roundToInt
* @param swipeThreshold Minimum drag distance before any [SwipeAction] is
* activated and can be swiped.
*
* @param swipeMaxDistance Maximum distance that can be swiped.
* 0.dp means that the [SwipeAction] can be swiped as far as you want.
*
* @param swipeFrictionEasing Easing function that determines how fast the
* [SwipeAction] is swiped.
*
* @param backgroundUntilSwipeThreshold Color drawn behind the content until
* [swipeThreshold] is reached. When the threshold is passed, this color is
* replaced by the currently visible [SwipeAction]'s background.
Expand All @@ -46,11 +54,17 @@ fun SwipeableActionsBox(
startActions: List<SwipeAction> = emptyList(),
endActions: List<SwipeAction> = emptyList(),
swipeThreshold: Dp = 40.dp,
swipeMaxDistance: Dp = swipeThreshold * 3f,
swipeFrictionEasing: Easing = EaseIn,
backgroundUntilSwipeThreshold: Color = Color.DarkGray,
content: @Composable BoxScope.() -> Unit
) = Box(modifier) {
state.also {
it.swipeThresholdPx = LocalDensity.current.run { swipeThreshold.toPx() }
LocalDensity.current.run {
it.swipeThresholdPx = swipeThreshold.toPx()
it.swipeMaxDistancePx = swipeMaxDistance.toPx()
}
it.swipeFrictionEasing = swipeFrictionEasing
val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl
it.actions = remember(endActions, startActions, isRtl) {
ActionFinder(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package me.saket.swipe

import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.Easing
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.tween
import androidx.compose.foundation.MutatePriority
import androidx.compose.foundation.gestures.DraggableState
Expand Down Expand Up @@ -43,6 +45,8 @@ class SwipeableActionsState internal constructor() {

internal var layoutWidth: Int by mutableIntStateOf(0)
internal var swipeThresholdPx: Float by mutableFloatStateOf(0f)
internal var swipeMaxDistancePx: Float by mutableFloatStateOf(0f)
internal var swipeFrictionEasing: Easing by mutableStateOf(LinearEasing)
internal val ripple = SwipeRippleState()

internal var actions: ActionFinder by mutableStateOf(
Expand All @@ -63,6 +67,20 @@ class SwipeableActionsState internal constructor() {
|| targetOffset == 0f
|| (targetOffset > 0f && canSwipeTowardsRight)
|| (targetOffset < 0f && canSwipeTowardsLeft)

// How to deal with the side that has multiple actions?
// temporarily limit to enable friction for the side that only has one action
val isAllowedForFriction = (targetOffset > 0f && actions.left.size == 1)
|| (targetOffset < 0f && actions.right.size == 1)

if (swipeMaxDistancePx > 0f && isAllowed && isAllowedForFriction) {
val progress = swipeFrictionEasing.transform(abs(offsetState.value) / swipeMaxDistancePx)
val progressReverse = (1f - progress).coerceIn(0f, 1f)

offsetState.value += delta * progressReverse
return@DraggableState
}

offsetState.value += if (isAllowed) delta else delta / 10
}

Expand Down