I am using from bellow class
for detect swipe
in recyclerView
:
open class OnSwipeTouchListener(context: Context) : View.OnTouchListener {
var context: Context? = context
private val gestureDetector = GestureDetector(context, GestureListener())
fun onTouchs(event: MotionEvent): Boolean {
return gestureDetector.onTouchEvent(event)
}
private inner class GestureListener : GestureDetector.SimpleOnGestureListener() {
private val SWIPE_THRESHOLD = 100
private val SWIPE_VELOCITY_THRESHOLD = 100
override fun onDown(e: MotionEvent): Boolean {
return true
}
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
onTouchs(e)
return true
}
override fun onFling(@NonNull e1: MotionEvent,
@NonNull e2: MotionEvent,
@NonNull velocityX: Float,
@NonNull velocityY: Float): Boolean {
val result = false
try {
val diffY = e2.y - e1.y
val diffX = e2.x - e1.x
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
//onSwipeRight()
} else {
onSwipeLeft()
}
}
} else {
// onTouch(e);
}
} catch (exception: Exception) {
exception.printStackTrace()
Crashlytics.logException(exception)
}
return result
}
}
// @SuppressLint("ClickableViewAccessibility")
override fun onTouch(@NonNull v: View, @NonNull event: MotionEvent): Boolean {
v.performClick()
return gestureDetector.onTouchEvent(event)
}
//open fun onSwipeRight() {}
open fun onSwipeLeft() {}
}
But when I scrolling to end list get me bellow crash when I arrive to end list:
java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter e1
at xx.xx.xx.tools.OnSwipeTouchListener$GestureListener.onFling(OnSwipeTouchListener.kt)
at android.view.GestureDetector.onTouchEvent(GestureDetector.java:667)
at xx.xx.xx.tools.OnSwipeTouchListener.onTouch(OnSwipeTouchListener.kt:65)
And here is my SwipeController.kt
:
internal class SwipeController(private val swipeControllerInter: SwipeControllerInter) : ItemTouchHelper.Callback() {
private var swipeBack = false
interface SwipeControllerInter {
fun left()
// fun right()
}
override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
return makeMovementFlags(0, LEFT or RIGHT)
}
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
return false
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
}
override fun convertToAbsoluteDirection(flags: Int, layoutDirection: Int): Int {
if (swipeBack) {
swipeBack = false
return 0
}
return super.convertToAbsoluteDirection(flags, layoutDirection)
}
override fun onChildDraw(c: Canvas,
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
dX: Float, dY: Float,
actionState: Int, isCurrentlyActive: Boolean) {
if (actionState == ACTION_STATE_SWIPE) {
if (dX > 0) {
// then swiping right.
//swipeControllerInter.right()
} else if (dX < 0) {
// then swiping left.
swipeControllerInter.left()
}
// If dX == 0 then at at start position.
} else {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
}
if (actionState == ACTION_STATE_SWIPE) {
setTouchListener(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
}
@SuppressLint("ClickableViewAccessibility")
private fun setTouchListener(c: Canvas,
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
dX: Float, dY: Float,
actionState: Int,
isCurrentlyActive: Boolean) {
recyclerView.setOnTouchListener { v, event ->
swipeBack = event.action == MotionEvent.ACTION_CANCEL || event.action == MotionEvent.ACTION_UP
false
}
}
}
And I am using in my MainFragment.kt
:
val swipeController = SwipeController(this)
val itemTouchhelper = ItemTouchHelper(swipeController)
itemTouchhelper.attachToRecyclerView(recycler_view)
recycler_view.setOnTouchListener(object : OnSwipeTouchListener(activity!!) {
override fun onSwipeLeft() {
val intent = Intent(activity, MainActivityMou::class.java)
intent.putExtra("ONE", 1)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
startActivity(intent)
activity!!.finish()
}
})
Resolved my problem, I changed onTouch
to:
override fun onTouch(v: View, event: MotionEvent): Boolean {
if (event.action == MotionEvent.ACTION_MOVE) {
v.performClick()
return gestureDetector.onTouchEvent(event)
} else {
return false
}
}
OR:
override fun onFling(e1: MotionEvent,
e2: MotionEvent,
velocityX: Float,
velocityY: Float): Boolean {
val result = false
if(e1 != null && e2 != null){
try {
val diffY = e2.y - e1.y
val diffX = e2.x - e1.x
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
//onSwipeRight()
} else {
onSwipeLeft()
}
}
} else {
// onTouch(e);
}
} catch (exception: Exception) {
exception.printStackTrace()
Crashlytics.logException(exception)
}
}
return result
}
}