Android 未检测到具有nestedscrollview和recycleviews的viewgroup的OnTouchListener
我正在将触控监听器添加到父视图中,以检测滑动手势。我的布局有一个嵌套的scrollview和三个RecycleView,但是我的touchevent没有被触发,我认为父级没有得到touchIntercept。在这种情况下,我希望constraintLayout处理触摸事件 XMLAndroid 未检测到具有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
<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);