【问题标题】:Is there a way to only trigger Child's gestureDetector?有没有办法只触发孩子的手势检测器?
【发布时间】:2019-04-22 14:20:56
【问题描述】:

我已将我的 Activity 设置为具有检测左右滑动的手势检测器Compat,但我的 Activity 中也有一个水平的 RecyclerView。

当我尝试滚动 RecyclerView Activity 时,getsureDetector 也会触发,这是不可取的。

如果有帮助,这里是与gestureDetector相关的代码。

private GestureDetectorCompat mDetector;
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
mDetector = new GestureDetectorCompat(this, new SwipeDetector());
public boolean onTouchEvent(MotionEvent event){
        this.mDetector.onTouchEvent(event);
        return super.onTouchEvent(event);
    }

public boolean dispatchTouchEvent(MotionEvent ev){
        if (mDetector != null){
            if (mDetector.onTouchEvent(ev)){
                return true;
            }
        }
        return super.dispatchTouchEvent(ev);
    }

public class SwipeDetector extends GestureDetector.SimpleOnGestureListener{
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY){

            if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH){
                return false;
            }

            if( e2.getX() > e1.getX() ){
                if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY){
                    Left();
                    return true;
                }
            }

            if( e1.getX() > e2.getX() ){
                if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY){
                    Right();
                    return true;
                }
            }
            return false;
        }
    }

【问题讨论】:

    标签: java android gesturedetector


    【解决方案1】:

    要仅触发RecyclerView 的触摸事件而不将它们传递回父视图,您需要通过在相应的触摸方法中返回 true 来“使用”该事件,如下所示:

    recyclerView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    return true; //consume touch event
                }
            });
    

    此外,在您的父视图(活动)的 dispatchTouchEvent 中删除对 onTouchEvent() 的调用,以便在触摸事件传播到其子视图之前它不会触发触摸事件(在您的情况下, RecyclerView) 并被消费。


    或者,您可以拦截传递给RecyclerView 的所有触摸事件,并通过在 RecyclerView 的项目触摸侦听器中覆盖 onInterceptTouchEvent 自己处理它们(例如有条件地使用它们)。当您还必须处理 RecyclerView 中的子视图并希望有条件地让子视图获取或不获取触摸事件(调度它们)时,这很有帮助。一个例子是这样的:

    recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener(){
    
                @Override
                public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
                    return true;
                }
    
                @Override
                public void onTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
    
                }
    
                @Override
                public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
    
                }
            });
    

    您还可以通过检查传入的触摸事件/recyclerview 状态的操作并返回 true 以使用或 false 以传递到其他父视图来更精确地控制何时拦截事件以及何时不拦截事件。例如:

    @Override
    public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
        if (e.getAction() == MotionEvent.ACTION_DOWN && rv.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING) {
            Log.d(TAG, "onInterceptTouchEvent: click performed");
            rv.findChildViewUnder(e.getX(), e.getY()).performClick();
            return true;
        }
        return false;
    }
    

    【讨论】:

    • 实际上我还没有触及 recyclerview 触摸事件,所以它们是默认的,我只需要它在项目多于空间时滚动以显示它们,就像默认情况下一样。我可以以某种方式避免重写此功能,还是应该 @Override 它并复制粘贴默认代码并将 return false(我假设存在)更改为 return true?
    • 如果您将onTouchEvent 留空,我认为默认行为将保留。你需要做的就是改变onInterceptTouchEvent的行为
    • “默认代码”是什么意思?你有 RecyclerView 的触摸事件的其他代码吗?如果是这样,您使用的是什么,您可能仍然可以覆盖onInterceptTouchEvent,但它在其他地方。但是,如果您没有其他代码,只需修改默认的onInterceptTouchEvent 并保留所有其他方法就可以了
    • 基本上,如果您没有任何代码来处理 RecyclerViews,那么我的答案中的示例应该可以正常工作,并且不应更改所有默认行为(除了消耗当然是事件)。
    • 我的意思是查找默认情况下的完成方式,然后复制粘贴并更改它。不,没有其他代码,实际上,它是一个非常简单的 RecyclerView。无论如何你所说的看起来正是我需要的,但我尝试将onInterceptTouchEvent设置为return true,现在它根本不会滚动,将它设置为false确实让我滚动RecyclerView所以功能是还在那里
    猜你喜欢
    • 2011-01-30
    • 1970-01-01
    • 2017-06-26
    • 2021-12-26
    • 1970-01-01
    • 2012-03-02
    • 2011-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多