未使用 nestedscrollview 和 recycleviews 检测视图组的 OnTouchListener
not detecting OnTouchListener for viewgroup with nestedscrollview and recycleviews
我正在向父视图添加触摸侦听器以检测滑动手势。我的布局有一个嵌套的滚动视图和三个回收视图,但我的 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>
Activity
public class TableViewActivity extends BaseActivity implements CustomAdapterGames.OnGameClickListener {
private ConstraintLayout constraintLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_table_view);
constraintLayout = findViewById(R.id.table_view_main_constraint_layout);
constraintLayout.requestDisallowInterceptTouchEvent(true);
recyclerViewGames = findViewById(R.id.table_view_recycle_view_games);
adapterOdds1 = new CustomAdapterOdds(this, Games, this, GamesHashMap.get(viewPagerColFirst), SitesList, viewPagerColFirst);
configRecyclerViewGames(recyclerViewGames, adapterGames);
}
}
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;
}
在这个任务上花了几个小时之后,我终于弄清楚了是什么导致了这个问题。我正在发布答案,以便其他人可以受益。
这是我的 OnSwipeTouchListener
Class,它使用 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
的接口,您可以在 activity.
中实施
public interface OnSwipeListener
{
//public void onUpwardsSwipe();
//public void onDownwardsSwipe();
public void onLeftwardsSwipe();
public void onRightwardsSwipe();
}
您必须在 activity 中 override
手势检测器 onTouchIntercept
。
@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);
我正在向父视图添加触摸侦听器以检测滑动手势。我的布局有一个嵌套的滚动视图和三个回收视图,但我的 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>
Activity
public class TableViewActivity extends BaseActivity implements CustomAdapterGames.OnGameClickListener {
private ConstraintLayout constraintLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_table_view);
constraintLayout = findViewById(R.id.table_view_main_constraint_layout);
constraintLayout.requestDisallowInterceptTouchEvent(true);
recyclerViewGames = findViewById(R.id.table_view_recycle_view_games);
adapterOdds1 = new CustomAdapterOdds(this, Games, this, GamesHashMap.get(viewPagerColFirst), SitesList, viewPagerColFirst);
configRecyclerViewGames(recyclerViewGames, adapterGames);
}
}
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;
}
在这个任务上花了几个小时之后,我终于弄清楚了是什么导致了这个问题。我正在发布答案,以便其他人可以受益。
这是我的 OnSwipeTouchListener
Class,它使用 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
的接口,您可以在 activity.
public interface OnSwipeListener
{
//public void onUpwardsSwipe();
//public void onDownwardsSwipe();
public void onLeftwardsSwipe();
public void onRightwardsSwipe();
}
您必须在 activity 中 override
手势检测器 onTouchIntercept
。
@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);