Andorid 中TouchEvent理解(四)滑动冲突的解决

来源:互联网 发布:mac 查看局域网所有ip 编辑:程序博客网 时间:2024/06/07 03:52

理解了TouchEvent之后,就是为了更好的解决滑动冲突。网上找到两种的解决办法,因为不一定非要固定的方法解决,就先记录这两种方式,并写了个小Demo.

转载自 http://blog.csdn.net/a992036795/article/details/51735501 

解决横竖滑动冲突,水平也是一样的,只是判定条件就需要根据具体情况来处理了。

1)外部拦截解决,在ViewGroup来决定传递来的事件由自己处理还是交给ChildView来处理。修改parentView就可了。

/**     * 拦截事件     * @param ev     * @return     */    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        boolean intercepted = false;        int x = (int) ev.getX();        int y = (int) ev.getY();        switch (ev.getAction()) {            /*如果拦截了Down事件,则子类不会拿到这个事件序列*/            case MotionEvent.ACTION_DOWN:                lastXIntercept = x;                lastYIntercept = y;                intercepted = false;                if (!mScroller.isFinished()) {                    mScroller.abortAnimation();                    intercepted = true;                }                break;            case MotionEvent.ACTION_MOVE:                final int deltaX = x - lastXIntercept;                final int deltaY = y - lastYIntercept;                /*根据条件判断是否拦截该事件*/                if (Math.abs(deltaX) > Math.abs(deltaY)) {                    intercepted = true;                } else {                    intercepted = false;                }                break;            case MotionEvent.ACTION_UP:                intercepted = false;                break;        }        lastXIntercept = x;        lastYIntercept = y;        return intercepted;    }

关键部分就是重写onInterceptTouchEvent这个方法,来完成拦截,这里在Down的时候,没有拦截事件,这样就能够找到TargetView,可以将事件传递到target,但是在MOVE的时候写了逻辑,需要拦截条件:


X方向上的滑动大于Y方向的滑动的就返回true自己处理,切换LIstView。

X方向上的滑动小于Y方向的滑动就返回false交由ListView处理,ListView上下滚动。



2)内部拦截解决,在parentView中,拦截逻辑如下:


 /**     * 拦截事件     * @param ev     * @return     */    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        if (ev.getAction() == MotionEvent.ACTION_DOWN) {            if (!mScroller.isFinished()) {                mScroller.abortAnimation();                return true;            }            return false;        } else {            return true;        }    }

Down事件不拦截,就可以找打targetView,后续的事件才有机会传递下去,其他事件统一都拦截掉,ChildView的修改如下。

/**     * 使用 outter.requestDisallowInterceptTouchEvent();     * 来决定父控件是否对事件进行拦截     *     * @param ev     * @return     */    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        int x = (int) ev.getX();        int y = (int) ev.getY();        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                mHorizontalEx2.requestDisallowInterceptTouchEvent(true);    //设置标记为不parent让拦截                break;            case MotionEvent.ACTION_MOVE:                final int deltaX = x - lastXIntercepted;                final int deltaY = y - lastYIntercepted;                if (Math.abs(deltaX) > Math.abs(deltaY)) {                    mHorizontalEx2.requestDisallowInterceptTouchEvent(false);   //设置标记为让parent拦截                }                break;            case MotionEvent.ACTION_UP:                break;        }        lastXIntercepted = x;        lastYIntercepted = y;        return super.dispatchTouchEvent(ev);    }

在ViewGroup中,贴一段代码

if (actionMasked == MotionEvent.ACTION_DOWN                    || mFirstTouchTarget != null) {                final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;                if (!disallowIntercept) {                    intercepted = onInterceptTouchEvent(ev);                    ev.setAction(action); // restore action in case it was changed                } else {                    intercepted = false;                }            } else {                // There are no touch targets and this action is not an initial down                // so this view group continues to intercept touches.                intercepted = true;            }

这里当时其他的事件的时候由于targe!=null,可以在这里根据Flag决定是否调用这个拦截函数。

requestDisallowInterceptTouchEvent(true)就是设置的mFlag,为FLAGDISALL_DISALLOW_INTERCETP,上面的parentView中的重写之后,当其他事件只要调用就是拦截下来,由parent处理。

targetView中定义逻辑,当

X方向上的滑动大于Y方向的滑动就让parent拦截下来,parent处理

X方向上的滑动小于Y方向的滑动就不让parent拦截下来,自己处理

这样在View内部就可以干涉到parent的事件处理过程。来决定谁来处理这些事件



demo地址点击打开链接


阅读全文
0 0
原创粉丝点击