您的位置:首页 > 其它

onInterceptTouchEvent的ACTION_MOVE事件不执行

2016-12-28 16:25 459 查看

前言

转载请注明出处:http://blog.csdn.net/dreamsever/article/details/53907691

最近在学习自定义ViewGroup的时候遇到一个问题,就是onInterceptTouchEvent的ACTION_MOVE事件不触发,这样我就无法实现滑动效果。需求是想自定义一个ViewGroup里面的多个子控件可以左右滑动

大致需求类似这里http://www.jianshu.com/p/67e4d1f7dc08 我按照作者的代码写到我的自定义的HorizontalViewgroup里面后发现无法左右滑动,但是作者的是可以的,tell me why?

为什么

然后我就打印监听事件

12-28 13:50:28.751 16214-16214/com.example.first D/HorizontalViewgroup: onInterceptTouchEvent:::ACTION_DOWN
12-28 13:50:28.753 16214-16214/com.example.first D/HorizontalViewgroup: return super.onInterceptTouchEvent(ev):::false
12-28 13:50:28.754 16214-16214/com.example.first D/HorizontalViewgroup: onTouchEvent:::ACTION_DOWN
12-28 13:50:28.754 16214-16214/com.example.first D/HorizontalViewgroup: return super.onTouchEvent(event):::false


从打印的日志可以看出当我在这个自定义的ViewGroup上滑动它根本没有触发MotionEvent.ACTION_MOVE事件,我就想这不可能啊,于是我就去网上搜了一下,然后我就找了两个链接:

http://stackoverflow.com/questions/23725102/onintercepttouchevent-never-receives-action-move

http://stackoverflow.com/questions/13283827/onintercepttouchevent-only-gets-action-down

官网文档:

https://developer.android.com/reference/android/view/ViewGroup.html#onInterceptTouchEvent%28android.view.MotionEvent%29

官网有这样一段说明:

onInterceptTouchEvent

Added in API level 1

boolean onInterceptTouchEvent (MotionEvent ev)

Implement this method to intercept all touch screen motion events. This allows you to watch events as they are dispatched to your children, and take ownership of the current gesture at any point.

Using this function takes some care, as it has a fairly complicated interaction with View.onTouchEvent(MotionEvent), and using it requires implementing that method as well as this one in the correct way. Events will be received in the following order:

You will receive the down event here.

The down event will be handled either by a child of this view group, or given to your own onTouchEvent() method to handle; this means you should implement onTouchEvent() to return true, so you will continue to see the rest of the gesture (instead of looking for a parent view to handle it). Also, by returning true from onTouchEvent(), you will not receive any following events in onInterceptTouchEvent() and all touch processing must happen in onTouchEvent() like normal.

For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target’s onTouchEvent().

If you return true from here, you will not receive any following events: the target view will receive the same event but with the action ACTION_CANCEL, and all further events will be delivered to your onTouchEvent() method and no longer appear here.

ViewGroup源码里面:

/**
* Implement this method to intercept all touch screen motion events.  This
* allows you to watch events as they are dispatched to your children, and
* take ownership of the current gesture at any point.
*
* <p>Using this function takes some care, as it has a fairly complicated
* interaction with {@link View#onTouchEvent(MotionEvent)
* View.onTouchEvent(MotionEvent)}, and using it requires implementing
* that method as well as this one in the correct way.  Events will be
* received in the following order:
*
* <ol>
* <li> You will receive the down event here.
* <li> The down event will be handled either by a child of this view
* group, or given to your own onTouchEvent() method to handle; this means
* you should implement onTouchEvent() to return true, so you will
* continue to see the rest of the gesture (instead of looking for
* a parent view to handle it).  Also, by returning true from
* onTouchEvent(), you will not receive any following
* events in onInterceptTouchEvent() and all touch processing must
* happen in onTouchEvent() like normal.
* <li> For as long as you return false from this function, each following
* event (up to and including the final up) will be delivered first here
* and then to the target's onTouchEvent().
* <li> If you return true from here, you will not receive any
* following events: the target view will receive the same event but
* with the action {@link MotionEvent#ACTION_CANCEL}, and all further
* events will be delivered to your onTouchEvent() method and no longer
* appear here.
* </ol>
*
* @param ev The motion event being dispatched down the hierarchy.
* @return Return true to steal motion events from the children and have
* them dispatched to this ViewGroup through onTouchEvent().
* The current target will receive an ACTION_CANCEL event, and no further
* messages will be delivered here.
*/
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}


奈何不知道是Google的工程师表达有问题还是我英语水平有限,照着上面的说明我发现怎么都解释不了日志打印的情况,好在已经有大牛帮我们总结好了,链接:

http://daemon369.github.io/android/2014/08/17/android-onInterceptTouchEvent-onTouchEvent

我从里面摘录了一段解释:

实现onInterceptTouchEvent方法可以用来拦截父ViewGroup传递下来的所有触屏事件,可以将所有触屏事件交由此ViewGroup自身的onTouchEvent来处理,也可以继续传递给其子View来处理。

onInterceptTouchEvent方法对触屏事件的拦截处理需要和onTouchEvent方法配合使用。

down事件首先传递到onInterceptTouchEvent方法中

onInterceptTouchEvent返回false表示将down事件交由子View来处理;若某一层子View的onTouchEvent返回了true,后续的move、up等事件都将先传递到ViewGroup的onInterceptTouchEvent的方法,并继续层层传递下去,交由子View处理;若子View的onTouchEvent都返回了false,则down事件将交由该ViewGroup的onTouchEvent来处理;如果ViewGroup的onTouchEvent返回false,down传递给父ViewGroup,后续事件不再传递给该ViewGroup;如果ViewGroup的onTouchEvent返回true,后续事件不再经过该ViewGroup的onInterceptTouchEvent方法,直接传递给onTouchEvent方法处理

onInterceptTouchEvent返回ture,down事件将转交该ViewGroup的onTouchEvent来处理;若onTouchEvent返回true,后续事件将不再经过该ViewGroup的onInterceptTouchEvent方法,直接交由该ViewGroup的onTouchEvent方法处理;若onTouchEvent方法返回false,后续事件都将交由父ViewGroup处理,不再经过该ViewGroup的onInterceptTouchEvent方法和onTouchEvent方法

看来onInterceptTouchEvent的ACTION_MOVE事件不执行的原因就是子view的down事件返回了fasle,然后ViewGroup的onTouchEvent 的down事件返回false,后续事件不再传递给该ViewGroup了。。

总结

自定义view路漫漫其修远兮,还有很多坑没有遇到过,手势,事件分发这块还要多练多学
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息