关于listview重写onintercepttouchevent不响应move和up事件
来源:互联网 发布:网络营销推广软件 编辑:程序博客网 时间:2024/06/03 14:42
首先来讲讲viewgroup的事件分发机制(盗来的图):
首先执行diapatchtouch,在diapatchtouch中调用onintercepttouchevent,在其中判断有没有拦截,如果拦截了就不调用子view的diapatchtouch,调用自身的touch事件,如果不拦截就调用子view 的diapatchtouch,执行view的事件分发机制。
这里也再说说view的分发机制好了:首先必定的dispatchTouch
public boolean dispatchTouchEvent(MotionEvent event) { if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && mOnTouchListener.onTouch(this, event)) { return true; } return onTouchEvent(event);}mOnTouchListener就是我们setontouchlistner时候赋的值,这个值只要我们set了就不会空,第二个判断是是否可点击,最后一个就是我们在setontouchlistener中重写的那个touch方法,在这里如果我们的touch返回false的会就继续调用ontouchevent方法,在其中会调用onclick方法。还有一个要注意的地方,当dispatchTouchEvent在进行事件分发的时候,只有前一个action返回true,才会触发后一个action
listview也是viewgroup,所以讲了上面的分发机制有助于我们分析我们的问题:重写listview中的onintercepttouchevent的时候竟然没有响应move和up事件,也就是一个viewgroup的onintercepttouchevent的move和up没有调用,看看上面的图,我们就知道是在dispatchtouch调用的onintercepttouchevent,那就去看下listview的dispatchtouch的方法中到底做了什么手脚。一进去看发现listview中没有重写这个方法,他的父类(AbsListView)中也没有,一直往上跟,只到viewgroup才有这个方法:
public boolean dispatchTouchEvent(MotionEvent ev) { final int action = ev.getAction(); final float xf = ev.getX(); final float yf = ev.getY(); final float scrolledXFloat = xf + mScrollX; final float scrolledYFloat = yf + mScrollY; final Rect frame = mTempRect; boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0; if (action == MotionEvent.ACTION_DOWN) { if (mMotionTarget != null) { mMotionTarget = null; } if (disallowIntercept || !onInterceptTouchEvent(ev)) { ev.setAction(MotionEvent.ACTION_DOWN); final int scrolledXInt = (int) scrolledXFloat; final int scrolledYInt = (int) scrolledYFloat; final View[] children = mChildren; final int count = mChildrenCount; for (int i = count - 1; i >= 0; i--) { final View child = children[i]; if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) { child.getHitRect(frame); if (frame.contains(scrolledXInt, scrolledYInt)) { final float xc = scrolledXFloat - child.mLeft; final float yc = scrolledYFloat - child.mTop; ev.setLocation(xc, yc); child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT; if (child.dispatchTouchEvent(ev)) { mMotionTarget = child; return true; } } } } } } boolean isUpOrCancel = (action == MotionEvent.ACTION_UP) || (action == MotionEvent.ACTION_CANCEL); if (isUpOrCancel) { mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT; } final View target = mMotionTarget; if (target == null) { ev.setLocation(xf, yf); if ((mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) { ev.setAction(MotionEvent.ACTION_CANCEL); mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT; } return super.dispatchTouchEvent(ev); } if (!disallowIntercept && onInterceptTouchEvent(ev)) { final float xc = scrolledXFloat - (float) target.mLeft; final float yc = scrolledYFloat - (float) target.mTop; mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT; ev.setAction(MotionEvent.ACTION_CANCEL); ev.setLocation(xc, yc); if (!target.dispatchTouchEvent(ev)) { } mMotionTarget = null; return true; } if (isUpOrCancel) { mMotionTarget = null; } final float xc = scrolledXFloat - (float) target.mLeft; final float yc = scrolledYFloat - (float) target.mTop; ev.setLocation(xc, yc); if ((target.mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) { ev.setAction(MotionEvent.ACTION_CANCEL); target.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT; mMotionTarget = null; } return target.dispatchTouchEvent(ev);}
上面就是源码(不同的版本会有差异),可以看到两个地方调用了onintercepttouchevent,而
final View target = mMotionTarget;
这句一般都是target = null,所以就是直接执行super.dispatchtouch,也就相当于执行一个view的dispatchtouch,直接就和touch、touchevent相关了,不再纠缠onintercepttouchevent,onintercepttouchevent也就不被调用了。说到这里我又去继承LinearLayout写了一个自定义的线性布局,然后重写了其中的dispatchtouch、onintercepttouchevent、ontouchEvent方法,然后惊奇的发现,连dispatchEvent都只响应down了,然后我不然ontouchevent返回super.ontouchevent,而是直接返回true(之前说了,返回true可以响应下一个action,false就是不响应),达到了和listview一样的效果。
说到这里就可以做一个总结了:对于所有的viewgroup,down了之后首先进入的就是dispatchtouch,随后判断是否拦截,不拦截分发给子view,拦截执行自己的ontouchevent方法,一般都是不拦截,然后发给子view,这个时候也会有差异,如果子view是可点击的,那么执行子view的dispatch和ontouchevent,否则的话还是会执行viewgroup的ontouchevent,紧接着move事件,很多viewgroup就直接不响应了(直接在down的dis中就返回了false,前提是子view不可点击),up和move差不多,都是根据子view来决定响不响应,更精确的说是子view的dispatchtouch方法的返回值。
差不多事件分发就这些内容,讲的很乱,大家自己自慢慢体会,有空我会整理出更好的文章。
大家可以自己去试验看看:重写dispatchtouch,直接返回true或者false(不调用supr.dspatchtouch)都不会再调用onintercepttouchevent和ontouchevent响应其中的任何事件
- 关于listview重写onintercepttouchevent不响应move和up事件
- view的onTouch事件不响应MOVE,up的解决办法
- view的onTouch事件不响应MOVE,up的解决办法
- android linearlayout OnTouch事件 只触发DOWN操作,不触发MOVE和UP操作?
- 关于listfragment中使用listview的点击事件不响应
- ListView点击事件不响应。
- Android开发中OnTouchListener接口方法onTouch的返回值问题 /不响应TouchListener中的UP和MOVE
- Android中的事件分发----DOWN、MOVE和UP
- android gridview listview onItemLongClick事件不响应
- ListView的setOnItemClickListener事件不响应
- ListView Item点击事件无效,不响应
- ListView的item点击事件不响应
- listview oclick事件不响应原因
- Android 关于嵌套listView时onItemClick事件不响应的解决办法
- Android关于嵌套listView时onItemClick事件不响应的解决方法
- Android 关于嵌套listView时onItemClick事件不响应的解决办法
- Android 关于嵌套listView时onItemClick事件不响应的解决办法
- Android 关于嵌套listView时onItemClick事件不响应的解决办法
- 如何运行从网上下载的iWatch项目详细步骤.Error: An App ID with identifier "*****" is not avaliable.
- Uiautomator测试分享(一)
- wayland&weston
- C++中的运算符重载
- selenium 'NoSuchElementException'
- 关于listview重写onintercepttouchevent不响应move和up事件
- 恢复出厂设置后HOME键失效问题
- Java类与对象的一些想法
- Java实现的死锁示例
- bigbluebutton开发
- 借鉴别人的pdo类,慢慢研究
- 本地升级的步骤
- android逆向分析中常用的smali注入代码
- NETBIOS名 和 Host名的不同