I'm working on an app that uses an animated character that has different animations triggered when the user taps on it and another animation when the user swipes on it. The issue is that the view registers the swipe gesture as a tap as well as shown below.
Here is the code handling the pointer input:
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.tooling.preview.Preview
import com.airbnb.lottie.compose.*
import com.lumen.tomo.R
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@Composable
fun ChatView() {
val initialAnimation = R.raw.cat_idle // Initial animation resource ID
val tapAnimation = R.raw.cat_headshake // Tap specific animation resource ID
val swipeAnimation = R.raw.cat_heart // Swipe specific animation resource ID
var animationRes by remember { mutableIntStateOf(initialAnimation) }
val idleAnimationComposition by rememberLottieComposition(LottieCompositionSpec.RawRes(initialAnimation))
val tapAnimationComposition by rememberLottieComposition(LottieCompositionSpec.RawRes(tapAnimation))
val swipeAnimationComposition by rememberLottieComposition(LottieCompositionSpec.RawRes(swipeAnimation))
val coroutineScope = rememberCoroutineScope() // Remember a CoroutineScope tied to the Composable's lifecycle
LottieAnimation(
composition = if (animationRes == initialAnimation) idleAnimationComposition else if (animationRes == tapAnimation) tapAnimationComposition else swipeAnimationComposition, // Choose based on animationRe
iterations = LottieConstants.IterateForever,
modifier = Modifier
.fillMaxSize()
.pointerInput(Unit) {
detectTapGestures(onTap = {
coroutineScope.launch {
animationRes = tapAnimation
delay(5000)
animationRes = initialAnimation
}
})
detectDragGestures { _, _ ->
coroutineScope.launch {
animationRes = swipeAnimation
delay(5000)
animationRes = initialAnimation
}
}
}
)
}
Have a look at the official documentation:
Internally, the
detectTapGestures
method blocks the coroutine, and the second detector is never reached. If you need to add more than one gesture listener to a composable, use separatepointerInput
modifier instances instead.
Please update your code and use two seperate pointerInput
Modifiers:
modifier = Modifier
.fillMaxSize()
.pointerInput(Unit) {
detectTapGestures(onTap = {
coroutineScope.launch {
animationRes = tapAnimation
delay(5000)
animationRes = initialAnimation
}
})
}
.pointerInput(Unit) {
detectDragGestures { _, _ ->
coroutineScope.launch {
animationRes = swipeAnimation
delay(5000)
animationRes = initialAnimation
}
}
}