在 recyclerView 中使用滑动触摸侦听器时,指定为非空的错误参数为空 - Android
Error parameter specified as non-null is null when use swipe touch listener in recyclerView - Android
我正在使用下面的 class
在 recyclerView
中检测 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 应用程序一样执行左右滑动。如果您在滑动项目时需要下方的按钮,请告诉我。
我正在使用下面的 class
在 recyclerView
中检测 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 应用程序一样执行左右滑动。如果您在滑动项目时需要下方的按钮,请告诉我。