将"向上滑动"和"向下滑动"侦听器添加到水平循环器视图中



我在linearLayout中有一个带有回收器视图的活动,我正在尝试检测该活动上的向上和向下滑动手势。我当前实现的问题是,如果我将滑动侦听器添加到linearLayout,它们不会被触发,如果我添加到recyclerView,它会左右滚动(因为它是水平的recyclerView(,而不是检测滑动

这是我的代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/linear">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context="com.cronlogy.hopstopandroid.activity.PlaceActivity"
tools:showIn="@layout/activity_place">
</android.support.v7.widget.RecyclerView>
</LinearLayout>

滑动监听器类:

public class OnSwipeTouchListener implements View.OnTouchListener {
private GestureDetector gestureDetector;
public OnSwipeTouchListener(Context c) {
gestureDetector = new GestureDetector(c, new GestureListener());
}
public boolean onTouch(final View view, final MotionEvent motionEvent) {
return gestureDetector.onTouchEvent(motionEvent);
}
private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
// Determines the fling velocity and then fires the appropriate swipe event accordingly
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
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 {
if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeDown();
} else {
onSwipeUp();
}
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeUp() {
}
public void onSwipeDown() {
}

}

这就是我在实际中的称呼

recyclerView.setOnTouchListener(new OnSwipeTouchListener(this) {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onSwipeDown() {
Toast.makeText(PlaceActivity.this, "Down", Toast.LENGTH_SHORT).show();
}
@Override
public void onSwipeLeft() {
}
@Override
public void onSwipeUp() {
Toast.makeText(PlaceActivity.this, "Up", Toast.LENGTH_SHORT).show();
}
@Override
public void onSwipeRight() {
}
});

有人能帮我吗?我如何在不滚动recyclerView中的项目的情况下检测滑动,或者如何将滚动侦听器附加到其父视图。

如果你在水平回收器视图上向上滑动,你需要一个自定义的回收器视图,比如:

class CustomRecyclerView : RecyclerView {
private lateinit var mDetector: GestureDetectorCompat
// =================================================================================================================
// CONSTRUCTORS
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : super(
context,
attrs,
defStyleAttr
)
override fun onInterceptTouchEvent(e: MotionEvent?): Boolean {
if (!mDetector.onTouchEvent(e)) {
return super.onInterceptTouchEvent(e)
}
return onInterceptTouchEvent(e)
}
fun initDetector(swippeListener: SwipeListener) {
mDetector = GestureDetectorCompat(context, object : OnSwipeListener() {
override fun onSwipe(direction: Direction): Boolean {
if (direction == Direction.up) {
//Do something here (in my case I try to open a new submenu)
swippeListener.openSubmenu()
return true
} else if (direction == Direction.down) {
//Do something here (in my case I try to close a new submenu)
swippeListener.closeSubmenu()
return true
}
return false
}
})
}
}

SwipeListener(用于将操作返回到我的类(:

interface SwipeListener {
fun openSubmenu()
fun closeSubmenu()
}

稍后您需要实现自己的OnSwipeListener:

我从获得此OnSwipeListener

如何检测左/右和上/下之间的滑动方向

open class OnSwipeListener : GestureDetector.SimpleOnGestureListener() {
override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
// Grab two events located on the plane at e1=(x1, y1) and e2=(x2, y2)
// Let e1 be the initial event
// e2 can be located at 4 different positions, consider the following diagram
// (Assume that lines are separated by 90 degrees.)
//
//
//          A  /
//            /
//       D   e1   B
//          /  
//         / C  
//
// So if (x2,y2) falls in region:
//  A => it's an UP swipe
//  B => it's a RIGHT swipe
//  C => it's a DOWN swipe
//  D => it's a LEFT swipe
//
val x1 = e1.x
val y1 = e1.y
val x2 = e2.x
val y2 = e2.y
val direction = getDirection(x1, y1, x2, y2)
return onSwipe(direction)
}
/** Override this method. The Direction enum will tell you how the user swiped.  */
open fun onSwipe(direction: Direction): Boolean {
return false
}
/**
* Given two points in the plane p1=(x1, x2) and p2=(y1, y1), this method
* returns the direction that an arrow pointing from p1 to p2 would have.
* @param x1 the x position of the first point
* @param y1 the y position of the first point
* @param x2 the x position of the second point
* @param y2 the y position of the second point
* @return the direction
*/
fun getDirection(x1: Float, y1: Float, x2: Float, y2: Float): Direction {
val angle = getAngle(x1, y1, x2, y2)
return Direction.fromAngle(angle)
}
/**
*
* Finds the angle between two points in the plane (x1,y1) and (x2, y2)
* The angle is measured with 0/360 being the X-axis to the right, angles
* increase counter clockwise.
*
* @param x1 the x position of the first point
* @param y1 the y position of the first point
* @param x2 the x position of the second point
* @param y2 the y position of the second point
* @return the angle between two points
*/
fun getAngle(x1: Float, y1: Float, x2: Float, y2: Float): Double {
val rad = Math.atan2((y1 - y2).toDouble(), (x2 - x1).toDouble()) + Math.PI
return (rad * 180 / Math.PI + 180) % 360
}

enum class Direction {
up,
down,
left,
right;

companion object {
/**
* Returns a direction given an angle.
* Directions are defined as follows:
*
* Up: [45, 135]
* Right: [0,45] and [315, 360]
* Down: [225, 315]
* Left: [135, 225]
*
* @param angle an angle from 0 to 360 - e
* @return the direction of an angle
*/
fun fromAngle(angle: Double): Direction {
return if (inRange(angle, 45f, 135f)) {
Direction.up
} else if (inRange(angle, 0f, 45f) || inRange(angle, 315f, 360f)) {
Direction.right
} else if (inRange(angle, 225f, 315f)) {
Direction.down
} else {
Direction.left
}
}
/**
* @param angle an angle
* @param init the initial bound
* @param end the final bound
* @return returns true if the given angle is in the interval [init, end).
*/
private fun inRange(angle: Double, init: Float, end: Float): Boolean {
return angle >= init && angle < end
}
}
}
}

最新更新