hey y’all! I’m building a swipe to reveal style co...
# compose
a
hey y’all! I’m building a swipe to reveal style component. so far I’m really happy with the results I was able to get with just the
.swipeable
modifier. I got this component working just by modifying the example from the docs! the issue is that the swipeable row also needs to be clickable, but when I use
.clickable
and
.swipeable
together, I’m seeing a ripple show when swiping is being invoked. anyone have a hunch about an idiomatic way around this?
j
You can remove ripple effect
Copy code
.clickable(
                interactionSource = MutableInteractionSource(),
                indication = null,
                onClick = { ... }
            )
Or, if you want ripple effect, you can get swipeable state and check if currentValue is equal to 1 (final swipe), and send ripple to it.
Copy code
.clickable(
                interactionSource = MutableInteractionSource(),
                indication = if(state.currentValue < 1 ) null else rememberRipple(),
                onClick = { ... }
            )
a
I’d prefer to keep the ripple 😄 And I like the idea of disabling it based on the swipe state, but I don’t think it gets me what I need. if I use a null ripple when the row is “closed” then clicking the closed row doesn’t show a ripple.
j
Copy code
.clickable(
                interactionSource = MutableInteractionSource(),
                indication = if(state.isAnimating) null else rememberRipple(),
                onClick = { ... }
            )
You can check animation too. Disable only in animation
a
this still doesn’t prevent a ripple when the row is fully closed and the user slides it open because at the moment the touch happens, there is no animation happening in the swipe, so the ripple fires.
j
I got it… You can try to implement gestures
Copy code
Modifier.pointerInput(Unit) {
    detectTapGestures(
        onPress = { /* Called when the gesture starts */ },
        onDoubleTap = { /* Called on Double Tap */ },
        onLongPress = { /* Called on Long Press */ },
        onTap = { /* Called on Tap */ }
    )
}
m
Seems like by default swipeable should act like a scroll container and delay the ripples or cancel it when swiped. We don't do it right now, but we should start doing this at some point. @jossiwolf
l
So ideal behavior is that a tap on the button causes a ripple and a drag does not. Would it suffice to ripple only when the component is released?
a
@matvei Good point! I hadn’t considered that this interaction works as intended in scrolling cases (like items with ripples in a
LazyColumn
, for example). I agree with you similar behavior for
.swipeable
would be great. is there any way I can help out? submitting an issue tracker perhaps?
@Lucas Kivi showing the ripple once released would work! but I’m not sure off hand how to delay the ripple until release… that would work though, because when the release happens, I could check to see if my offset is 0 and only then invoke the ripple.
the other thing I will note here is that the
clickable
onClick
lambda is working as expected. (
onClick
lambda is only called when the user taps the row without any swiping)
l
InteractionSource
exposes a
flow
of
Interactions
. One of these
Interactions
is
PressInteraction.Release
. Might be ugly but you could probably rig up a ripple based on that…
m
is there any way I can help out? submitting an issue tracker perhaps?
Please do file a FR yes, that would help
a
Done: https://issuetracker.google.com/u/1/issues/251809265 this is my first time doing this for compose, so please let me know if something about submitting the issue was wrong. thanks to all in this thread 🙇
j
Thank you! 🙂
r
Andrew: Not an answer to your question but you mentioned you modified an example from the docs: can you link that example here? I was looking at the
SwipeToDismiss
component but it appears it has been removed in Material 3; I’d like to know how it’s supposed to be done now. Thanks.
a
j
Fwiw we are looking to bring SwipeToDismiss to M3; no timeline yet though.
263 Views