Android 未检测到具有nestedscrollview和recycleviews的viewgroup的OnTouchListener

Android 未检测到具有nestedscrollview和recycleviews的viewgroup的OnTouchListener,android,touch,android-nestedscrollview,android-touch-event,Android,Touch,Android Nestedscrollview,Android Touch Event,我正在将触控监听器添加到父视图中,以检测滑动手势。我的布局有一个嵌套的scrollview和三个RecycleView,但是我的touchevent没有被触发,我认为父级没有得到touchIntercept。在这种情况下,我希望constraintLayout处理触摸事件 XML <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/andro

我正在将触控监听器添加到父视图中,以检测滑动手势。我的布局有一个嵌套的scrollview和三个RecycleView,但是我的touchevent没有被触发,我认为父级没有得到touchIntercept。在这种情况下,我希望constraintLayout处理触摸事件

XML

<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/table_view_main_constraint_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="@dimen/activity_horizontal_margin"
    android:layout_marginRight="@dimen/activity_horizontal_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".ui.table_view.TableViewActivity"
    tools:showIn="@layout/activity_table_view">


    <ProgressBar
        android:id="@+id/progress_table_view"
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminateTint="@color/colorFontWhite"
        android:translationZ="2dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.core.widget.NestedScrollView
        android:id="@+id/nested_scroll_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@id/content_table_view_layout_bottom"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/constraint_layout2"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <androidx.constraintlayout.widget.ConstraintLayout
                android:id="@+id/constraint_layout_spinners"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent">

                <Spinner
                    android:id="@+id/spinner_table_view_country"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/nav_header_vertical_spacing"
                    android:background="@drawable/shape_button_round_home"
                    android:gravity="center_vertical"
                    android:orientation="vertical"
                    android:popupBackground="@drawable/shape_spinner_gradient"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />

                <Spinner
                    android:id="@+id/spinner_table_view_league"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/nav_header_vertical_spacing"
                    android:background="@drawable/shape_button_round_home"
                    android:gravity="center_vertical"
                    style="spinner"
                    android:orientation="vertical"
                    android:popupBackground="@drawable/shape_spinner_gradient"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@+id/spinner_table_view_country" />

            </androidx.constraintlayout.widget.ConstraintLayout>

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/table_view_recycle_view_games"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:nestedScrollingEnabled="false"
                android:layout_marginEnd="@dimen/activity_horizontal_margin"
                app:layout_constraintEnd_toEndOf="@id/guideline5"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/constraint_layout_spinners" />

            <androidx.constraintlayout.widget.Guideline
                android:id="@+id/guideline5"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:orientation="vertical"
                app:layout_constraintGuide_percent="0.53"
                app:layout_constraintTop_toBottomOf="@id/constraint_layout_spinners" />

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/table_view_recycle_view_odds_1"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:orientation="horizontal"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toStartOf="@id/guideline6"
                app:layout_constraintStart_toStartOf="@id/guideline5"
                app:layout_constraintTop_toBottomOf="@id/constraint_layout_spinners"
                android:nestedScrollingEnabled="false" />
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/table_view_recycle_view_odds_2"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:orientation="horizontal"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="@id/guideline6"
                app:layout_constraintTop_toBottomOf="@id/constraint_layout_spinners"
                android:nestedScrollingEnabled="false" />

            <androidx.constraintlayout.widget.Guideline
                android:id="@+id/guideline6"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:orientation="vertical"
                app:layout_constraintGuide_percent="0.77"
                app:layout_constraintTop_toBottomOf="@id/constraint_layout_spinners" />

        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.core.widget.NestedScrollView>
 </androidx.constraintlayout.widget.ConstraintLayout>
Ontouch方法

@Override
    public boolean onTouch(View v, MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                downX = event.getX();
                downY = event.getY();
                //   return true;
            }
            case MotionEvent.ACTION_UP: {
                upX = event.getX();
                upY = event.getY();

                float deltaX = downX - upX;
                float deltaY = downY - upY;

                // swipe horizontal?
                if (Math.abs(deltaX) > MIN_DISTANCE) {
                    // left or right
                    if (deltaX < 0) {
                        Toast.makeText(TableViewActivity.this, "prev", Toast.LENGTH_SHORT).show();
                        return true;
                    }
                    if (deltaX > 0) {
                        Toast.makeText(TableViewActivity.this, "next", Toast.LENGTH_SHORT).show();
                        return true;
                    }
                } else {
                    Toast.makeText(TableViewActivity.this, "Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE, Toast.LENGTH_SHORT).show();
                }

                // swipe vertical?
                if (Math.abs(deltaY) > MIN_DISTANCE) {
                    // top or down
                    if (deltaY < 0) {
                        return true;
                    }
                    if (deltaY > 0) {
                        return true;
                    }
                } else {
                    Toast.makeText(TableViewActivity.this, "Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE, Toast.LENGTH_SHORT).show();
                }

                //     return true;
            }
        }
        return false;
    }
@覆盖
公共布尔onTouch(视图v,运动事件){
开关(event.getAction()){
case MotionEvent.ACTION\u DOWN:{
downX=event.getX();
downY=event.getY();
//返回true;
}
case MotionEvent.ACTION\u UP:{
upX=event.getX();
upY=event.getY();
浮动deltaX=downX-upX;
浮动三角洲=downY-upY;
//横扫?
如果(数学绝对值(deltaX)>最小距离){
//左还是右
如果(deltaX<0){
Toast.makeText(TableViewActivity.this,“prev”,Toast.LENGTH_SHORT.show();
返回true;
}
如果(deltaX>0){
Toast.makeText(TableViewActivity.this,“next”,Toast.LENGTH_SHORT.show();
返回true;
}
}否则{
Toast.makeText(TableViewActivity.this,“Swipe”仅为“+Math.abs(deltaX)+”长,至少需要“+MIN_距离,Toast.LENGTH_短).show();
}
//垂直滑动?
如果(数学绝对值(deltaY)>最小距离){
//自上而下
如果(三角洲<0){
返回true;
}
如果(三角洲>0){
返回true;
}
}否则{
Toast.makeText(TableViewActivity.this,“Swipe”仅为“+Math.abs(deltaX)+”长,至少需要“+MIN_距离,Toast.LENGTH_短).show();
}
//返回true;
}
}
返回false;
}

在花了几个小时完成这项任务后,我终于找到了问题的原因。我张贴的答案,以便其他人可以受益

这是我的
OnSwipeTouchListener
类,它使用
GestureDetector

public class OnSwipeTouchListener implements View.OnTouchListener {
    public final GestureDetector gestureDetector;
    Context context;
    private OnSwipeListener onSwipeListener;


    OnSwipeTouchListener(Context ctx, View mainView, OnSwipeListener onSwipeListener ) {
        gestureDetector = new GestureDetector(ctx, new GestureListener());
        mainView.setOnTouchListener(this);
        context = ctx;
        this.constraintLayout=constraintLayout;
        this.onSwipeListener = onSwipeListener;
    }

    float firstTouchX;
    @Override
    public boolean onTouch(View v, MotionEvent event) {


        switch(event.getAction()) {
            case MotionEvent.ACTION_DOWN:

            default:
                break;
        }
        return gestureDetector.onTouchEvent(event);
    }

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

        @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();
                        }
                        result = true;
                    }
                } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        //onSwipeBottom();
                    } else {
                        //onSwipeTop();
                    }
                    result = true;
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result;
        }
    }

    void onSwipeRight() {
        //Toast.makeText(context, "Swiped Right", Toast.LENGTH_SHORT).show();
        onSwipeListener.onRightwardsSwipe();

    }

    void onSwipeLeft() {
        //Toast.makeText(context, "Swiped Left", Toast.LENGTH_SHORT).show();
        onSwipeListener.onLeftwardsSwipe();
    }

  /*  void onSwipeTop() {
        //Toast.makeText(context, "Swiped Up", Toast.LENGTH_SHORT).show();
        onSwipeListener.onRightwardsSwipe();
    }

    void onSwipeBottom() {
        //Toast.makeText(context, "Swiped Down", Toast.LENGTH_SHORT).show();
        onSwipeListener.onRightwardsSwipe();
    }*/

}
可在活动中实现的
OnSwipeListener
接口

public interface OnSwipeListener
{
    //public void onUpwardsSwipe();
    //public void onDownwardsSwipe();
    public void onLeftwardsSwipe();
    public void onRightwardsSwipe();
}
 @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        onSwipeTouchListener.gestureDetector.onTouchEvent(event);
        // Be sure to call the superclass implementation
        return super.dispatchTouchEvent(event);
    }
在您的活动中,您必须
覆盖
手势检测器
onTouchIntercept

public interface OnSwipeListener
{
    //public void onUpwardsSwipe();
    //public void onDownwardsSwipe();
    public void onLeftwardsSwipe();
    public void onRightwardsSwipe();
}
 @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        onSwipeTouchListener.gestureDetector.onTouchEvent(event);
        // Be sure to call the superclass implementation
        return super.dispatchTouchEvent(event);
    }
现在,您可以使用
OnSwipeTouchListener
进行查看

onSwipeTouchListener = new OnSwipeTouchListener(this, findViewById(R.id.nested_scroll_view), this);