在 recyclerView 中使用滑动触摸侦听器时,指定为非空的错误参数为空 - Android

Error parameter specified as non-null is null when use swipe touch listener in recyclerView - Android

我正在使用下面的 classrecyclerView 中检测 swipe:

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() {}
}

但是当我滚动到末尾列表时,当我到达末尾列表时让我崩溃:

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)

这是我的 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
        }
    }
}

我正在 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()
    }
})

解决了我的问题,我把onTouch改成了:

override fun onTouch(v: View, event: MotionEvent): Boolean {
    if (event.action == MotionEvent.ACTION_MOVE) {
        v.performClick()
        return gestureDetector.onTouchEvent(event)
    } else {
        return false
    }
}

或:

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
        }
    }

滑动事件不需要额外的 class。因为这可以使用 ItemouchHelper class.

来完成
private void rightAndLeftSwipe() {
        ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT) {
            @Override
            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                return false;
            }

            @Override
            public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
                super.clearView(recyclerView, viewHolder);
            }
 @Override
            public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
                int postion = viewHolder.getAdapterPosition();

              /*----------Right swipe -----------*/
                if (direction == ItemTouchHelper.RIGHT) {
                  //todo perform your action
                }
                /*--------Left swipe--------*/
                if (direction == ItemTouchHelper.LEFT) {
                   //perform your action for left swipe
                }
            }

        };
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
        itemTouchHelper.attachToRecyclerView(binding.rvRecycler);
    }

以上代码将像 tinder 应用程序一样执行左右滑动。如果您在滑动项目时需要下方的按钮,请告诉我。