I've created a Carousel using MotionLayout by following this guide: https://developer.android.com/training/constraint-layout/motionlayout/carousel
I've gotten everything from this guide working - I can swipe through a carousel of items.
However, I'm having trouble adding an onClickListener to my carousel's items. I've tried setting the onClickListener in the adapter like so:
carousel.setAdapter(object : Carousel.Adapter {
override fun populate(view: View?, index: Int) {
view.setOnClickListener {
// do something
}
}
})
However, this makes the carousel unresponsive to swiping. When I try to swipe the carousel it executes my onClick function but doesn't execute my onSwipe transition.
My question is, what is the proper way to set an onClick function for a Carousel item?
While searching for an answer, I've seen a few posts that reference Carousel.setOnItemClickListener()
. This is exactly what I need, but it seems to have been deprecated.
I've also seen posts to say to override onTouchListener and run your onClick code on the ACTION_UP event. I've tried a couple variations of this code snippet, but haven't been able to get it to work:
carousel.setAdapter(object : Carousel.Adapter {
override fun populate(view: View?, index: Int) {
view.setOnTouchListener { view, motionEvent ->
if(motionEvent.action == MotionEvent.ACTION_UP) {
// do something
}
view.performClick()
}
}
})
Would really appreciate any help!
No better solution
You could have override parent MotionLayout class like this.Intercept the slide event
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import androidx.constraintlayout.motion.widget.MotionLayout
import kotlin.math.abs
/**
* @author : litao
* @email : onresume@live.com
* @date : 2022/5/31 5:31 下午
*/
class TestMotionLayout constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
) : MotionLayout(context, attrs, defStyleAttr) {
private var mInitX = 0f
private var mInitY = 0f
private var mTouchSlop = 10
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
when (ev.actionMasked) {
MotionEvent.ACTION_DOWN -> {
mInitX = ev.x
mInitY = ev.y
}
MotionEvent.ACTION_MOVE -> {
val moveX = abs(ev.x - mInitX)
val moveY = abs(ev.y - mInitY)
if (moveX > mTouchSlop || moveY > mTouchSlop){
val obtain = MotionEvent.obtain(ev)
obtain.action = MotionEvent.ACTION_DOWN
dispatchTouchEvent(obtain)
onTouchEvent(obtain)
return true
}
}
MotionEvent.ACTION_UP -> {
}
}
return false
}
}
Worked for me