Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

事件分发机制 时间拦截 滑动冲突 MD


目录

事件分发机制分析案例

默认行为

触摸事件由Action_Down0、Aciton_UP1、Action_Move==2组成,其中一次完整的触摸事件中,Down只有一个、Up有一个或0个、Move有若干个(包括0个),一旦UP发生,就表明此次触摸事件已经结束了。

试验 0

1、当触摸根部的LinearLayout时:

  1. dispatchTouchEvent--root--按下
  2. onInterceptTouchEvent--root--按下
  3. onTouch--root--按下
  4. onTouchEvent--root--按下

2、当触摸子TextView时:

  1. dispatchTouchEvent--root--按下
  2. onInterceptTouchEvent--root--按下
  3. dispatchTouchEvent--TextView--tv--按下
  4. onTouch--tv--按下
  5. onTouchEvent--tv--按下
  6. onTouch--root--按下
  7. onTouchEvent--root--按下

3、当触摸子LinearLayout

  1. dispatchTouchEvent--root--按下
  2. onInterceptTouchEvent--root--按下
  3. dispatchTouchEvent--ll_child--按下
  4. onInterceptTouchEvent--ll_child--按下
  5. onTouch--ll_child--按下
  6. onTouchEvent--ll_child--按下
  7. onTouch--root--按下
  8. onTouchEvent--root--按下

4、当触摸孙子TextView时:

  1. dispatchTouchEvent--root--按下
  2. onInterceptTouchEvent--root--按下
  3. dispatchTouchEvent--ll_child--按下
  4. onInterceptTouchEvent--ll_child--按下
  5. dispatchTouchEvent--TextView--tv_child--按下
  6. onTouch--tv_child--按下
  7. onTouchEvent--tv_child--按下
  8. onTouch--ll_child--按下
  9. onTouchEvent--ll_child--按下
  10. onTouch--root--按下
  11. onTouchEvent--root--按下

5、当触摸一个具有点击事件的普通的子TextView时:

  1. dispatchTouchEvent--root--按下
  2. onInterceptTouchEvent--root--按下
  3. dispatchTouchEvent--TextView--null--按下
  4. onTouchEvent--null--按下
  5. dispatchTouchEvent--root--移动
  6. onInterceptTouchEvent--root--移动
  7. dispatchTouchEvent--TextView--null--移动
  8. onTouchEvent--null--移动
  9. //...后续所有Move事件都会收到
  10. dispatchTouchEvent--root--松开
  11. onInterceptTouchEvent--root--松开
  12. dispatchTouchEvent--TextView--null--松开
  13. onTouchEvent--null--松开

结论

不进行如何干涉的情况下:

即要满足以下所有条件:

  • 触摸点区域没有一个View的dispatchTouchEvent方法的返回值为true
  • 触摸点区域没有一个View的onTouchEvent方法和onTouch方法的返回值为true
  • 触摸点区域没有一个View有设置点击事件、长点击事件等会消耗触摸事件的方法

两个基本规律:

  • View的onInterceptTouchEvent方法是在dispatchTouchEvent方法中被调用的(如果dispatchTouchEvent方法返回true,则不会调用onInterceptTouchEvent方法),所以可以把dispatchTouchEvent方法和onInterceptTouchEvent方法看做一对方法。
  • View的onTouchEvent方法是在监听器回调方法onTouch之后被调用的,所以也可以把onTouch方法和onTouchEvent方法看做一对方法。

这么一划分的话,事件的分发过程就可以简化为对两对方法进行分析了(事实上,这种划分是合理的)。

对于 Down 事件

  • Down事件首先会从root逐级【下发】到最底层的View,下发的事件是通过dispatchTouchEvent方法传递的(当然,因为dispatchTouchEvent方法没有返回true,所以还会将Down事件传给自己的onInterceptTouchEvent方法,下同)。
  • 当Down事件从root逐级下发到最底层的那个View后,最底层的那个View的dispatchTouchEvent会将Down事件传给自己的 onTouch方法(当然因为onTouch没有返回true,所以还会将Down事件传给自己的onTouchEvent方法,下同)。
  • 由此便开始了Down事件的逐级【上传】过程,即Down事件将从最底层的那个View开始,逐级【上传】到root的 onTouch(和 onTouchEvent方法)。

Down事件的传递过程:

dTE父(包含-->oIT) --> dTE子 --> ... --> dTE底 --> onTouch底(包含-->onTE) --> ... --> onTouch子 --> onTouch父。

对于后续的 Move、UP 事件

  • 在分发完 Down 事件后( Down 事件一定会分发),其余的 Move、UP 事件将不再分发。
  • 也即任何 View 都不会收到后续的 Move、UP 事件,因为没有任何 View 需要处理本次触摸事件。

注意,上述案例中的第五种情况不满足上述条件,因为那个TextView具有点击事件,所以会导致能收到后续的触摸事件

dispatchTouchEvent 返回 true

试验 1

我们将子LinearLayoutdispatchTouchEvent 方法返回true,当触摸子LinearLayout孙子TextView时:

  1. dispatchTouchEvent--root--按下
  2. onInterceptTouchEvent--root--按下
  3. dispatchTouchEvent--ll_child--按下
  4. dispatchTouchEvent--root--移动
  5. onInterceptTouchEvent--root--移动
  6. dispatchTouchEvent--ll_child--移动
  7. //...后续所有Move事件都会收到
  8. dispatchTouchEvent--root--松开
  9. onInterceptTouchEvent--root--松开
  10. dispatchTouchEvent--ll_child--松开

试验 2

我们将孙子TextViewdispatchTouchEvent 方法返回true,当触摸孙子TextView时:

  1. dispatchTouchEvent--root--按下
  2. onInterceptTouchEvent--root--按下
  3. dispatchTouchEvent--ll_child--按下
  4. onInterceptTouchEvent--ll_child--按下
  5. dispatchTouchEvent--TextView--tv_child--按下
  6. dispatchTouchEvent--root--移动
  7. onInterceptTouchEvent--root--移动
  8. dispatchTouchEvent--ll_child--移动
  9. onInterceptTouchEvent--ll_child--移动
  10. dispatchTouchEvent--TextView--tv_child--移动
  11. //...后续所有Move事件都会收到
  12. dispatchTouchEvent--root--松开
  13. onInterceptTouchEvent--root--松开
  14. dispatchTouchEvent--ll_child--松开
  15. onInterceptTouchEvent--ll_child--松开
  16. dispatchTouchEvent--TextView--tv_child--松开

结论

  • 如果某个View的dispatchTouchEvent方法返回值为true(不管是普通View还是ViewGroup),则表明 这个具体的事件 的分发过程到此结束了。
  • 所以此View的所有子View都不会获取到这一个具体的事件
  • 但是此View的所有父View可以获取到此View能获取到的所有事件,因为此View获取的任何事件都是由根View逐级下发过来的。
  • 注意,分发结束只是针对当前这个具体的MotionEvent事件而言的,而不是针对整个事件链而言的,所以到后续所有事件仍会正常进行分发。
  • 所以,即使你在dispatchTouchEvent中没做任何判断就直接返回了true,后续所有的事件仍会正常进行分发。
  • 鉴于dispatchTouchEvent方法只是终止了某一具体事件的分发,而不是终止本次完整事件的分发,所以如果想在某种情况下终止接收后续的事件,用这个方法是不适合的。

onInterceptTouchEvent 返回 true

PS:只有 ViewGroup 才有 onInterceptTouchEvent 方法

试验 3

我们将子LinearLayoutonInterceptTouchEvent 方法返回true,当触摸子LinearLayout孙子TextView时:

  1. dispatchTouchEvent--root--按下
  2. onInterceptTouchEvent--root--按下
  3. dispatchTouchEvent--ll_child--按下
  4. onInterceptTouchEvent--ll_child--按下
  5. onTouch--ll_child--按下
  6. onTouchEvent--ll_child--按下
  7. onTouch--root--按下
  8. onTouchEvent--root--按下

结论

  • 如果一个 ViewGrouponInterceptTouchEvent方法返回 true,则代表此 ViewGroup 会拦截后续所有事件,因此,其子View后续将收不到任何Touch事件
  • 注意,ViewGroup拦截事件后会将当前事件传递给自己的 onTouchonTouchEvent 方法,然后继续执行事件的分发流程,即如果自己的 onTouchonTouchEvent 方法都返回false,会将事件传递给自己父ViewGrouponTouch方法,而不是在此终止事件的分发
  • 因此,我们可以认为:如果一个 ViewGrouponInterceptTouchEvent方法返回 true,则可以等价的认为这个ViewGroup隐藏了其所有子View(或者认为其没有任何子View),而其他过程和正常的事件分发过程完全一致
  • 鉴于此,我们经常是在onInterceptTouchEvent方法中拦截子View获取事件(目的往往是为了让自己能够处理后续事件)。

onInterceptTouchEventdispatchTouchEvent 方法的注意区别:

  • 返回 true 后,onInterceptTouchEvent 则会拦截后续所有事件的分发,而 dispatchTouchEvent 只是终止当前这一具体事件的分发。
  • onInterceptTouchEvent 会继续正常分发这一具体的事件,而 dispatchTouchEvent会直接结束分发这一具体的事件。

onTouchEvent 返回 true

试验 4

我们将子LinearLayoutonTouchEvent方法返回true

当触摸子LinearLayout时:

  1. dispatchTouchEvent--root--按下
  2. onInterceptTouchEvent--root--按下
  3. dispatchTouchEvent--ll_child--按下
  4. onInterceptTouchEvent--ll_child--按下
  5. onTouch--ll_child--按下
  6. onTouchEvent--ll_child--按下
  7. dispatchTouchEvent--root--移动
  8. onInterceptTouchEvent--root--移动
  9. dispatchTouchEvent--ll_child--移动
  10. onTouch--ll_child--移动
  11. onTouchEvent--ll_child--移动
  12. //...后续所有Move事件都会收到
  13. dispatchTouchEvent--root--松开
  14. onInterceptTouchEvent--root--松开
  15. dispatchTouchEvent--ll_child--松开
  16. onTouch--ll_child--松开
  17. onTouchEvent--ll_child--松开

当触摸孙子TextView时:

  1. dispatchTouchEvent--root--按下
  2. onInterceptTouchEvent--root--按下
  3. dispatchTouchEvent--ll_child--按下
  4. onInterceptTouchEvent--ll_child--按下
  5. dispatchTouchEvent--TextView--tv_child--按下
  6. onTouch--tv_child--按下
  7. onTouchEvent--tv_child--按下
  8. onTouch--ll_child--按下
  9. onTouchEvent--ll_child--按下
  10. dispatchTouchEvent--root--移动
  11. onInterceptTouchEvent--root--移动
  12. dispatchTouchEvent--ll_child--移动
  13. onTouch--ll_child--移动
  14. onTouchEvent--ll_child--移动
  15. //...后续所有Move事件都会收到
  16. dispatchTouchEvent--root--松开
  17. onInterceptTouchEvent--root--松开
  18. dispatchTouchEvent--ll_child--松开
  19. onTouch--ll_child--松开
  20. onTouchEvent--ll_child--松开

结论

首先可以发现,当触摸子LinearLayout孙子TextView时,两者的过程基本都是一致的,所以下面的关键是分析对比着两者的区别。

对于DOWN事件

  • 【下发过程】:当触摸孙子TextView时,虽然子LinearLayoutonTouchEvent方法返回了true,但是孙子TextViewdispatchTouchEvent方法仍会被调用,所以,View的onTouchEvent方法返回true并不会影响DOWN事件的正常下发。
  • 【上传过程】:首先DOWN事件会从最底层的孙子TextViewonTouchEvent方法上传给子LinearLayoutonTouchEvent方法,然后DOWN事件的上传过程就结束了,而不会继续上传给父View

面试题:

问:如果子View和父ViewGroup的onTouchEvent都返回true,哪个控件的onTouchEvent会执行?

答:子View的。

问:这种情况下,怎么让父ViewGroup的onTouchEvent执行?

答:让父ViewGroup的onInterceptTouchEvent方法返回 true即可。

结论:

  • onTouchEvent方法的返回值并不会影响DOWN事件的正常下发过程。
  • 如果一个View的onTouchEvent方法返回true,那么DOWN事件的上传过程将会在这里停止,所以此View所有父ViewonTouch方法和onTouchEvent方法都将不会被调用(这是一条核心的结论)。
  • 换句话说,如果一个View的onTouchEvent方法返回true,那么DOWN事件将会在传递到View的onTouchEvent方法后被完全消耗掉。

对于后续的 MOVE、UP 事件

我们假设上面那个onTouchEvent方法返回true的View名字为ViewA

  • ViewA其所有父ViewdispatchTouchEvent方法和onInterceptTouchEvent方法【都会】被调用。
  • ViewA的所有子ViewdispatchTouchEvent方法和onInterceptTouchEvent方法【都不会】被调用。
  • 仅ViewA的onTouch方法和onTouchEvent方法会被调用,或者说仅ViewA的onTouchEvent方法能够处理MOVE、UP事件。
  • 所以,onTouchEvent方法最核心的作用是用来告诉View树:后续的MOVE、UP事件到底应该从根View【传递】到哪个View去处理(PS:"传递"这个词用的非常好)。

完整的流程为

  • 一旦某个View的【onTouchEvent】返回true,当【DOWN】事件按照【正常的分发流程】逐级【下传】到【最底层的View】的【dispatchTouchEvent】后,【最底层的View】将通过其【onTouchEvent】逐级【上传】,直到上传到【此View】的【onTouchEvent】方法之后,DOWN事件将会被消耗掉;
  • 然而,此后的【MOVE、UP】事件在逐级【下传】到【此View】后将直接【结束】分发(而不会下传到最底层的View),并且在调用【此View】的onTouchEvent方法后被完全【消耗】掉。

试验 5

我们将孙子TextViewonTouchEvent方法返回true

当触摸孙子TextView时:

  1. dispatchTouchEvent--root--按下
  2. onInterceptTouchEvent--root--按下
  3. dispatchTouchEvent--ll_child--按下
  4. onInterceptTouchEvent--ll_child--按下
  5. dispatchTouchEvent--TextView--tv_child--按下
  6. onTouch--tv_child--按下
  7. onTouchEvent--tv_child--按下
  8. dispatchTouchEvent--root--移动
  9. onInterceptTouchEvent--root--移动
  10. dispatchTouchEvent--ll_child--移动
  11. onInterceptTouchEvent--ll_child--移动
  12. dispatchTouchEvent--TextView--tv_child--移动
  13. onTouch--tv_child--移动
  14. onTouchEvent--tv_child--移动
  15. dispatchTouchEvent--root--松开
  16. onInterceptTouchEvent--root--松开
  17. dispatchTouchEvent--ll_child--松开
  18. onInterceptTouchEvent--ll_child--松开
  19. dispatchTouchEvent--TextView--tv_child--松开
  20. onTouch--tv_child--松开
  21. onTouchEvent--tv_child--松开

可以发现和上面的情况完全一致,这里之所以分开,是因为上面的篇幅太长了,放在一起的话会让人比较难把握住重点信息。

测试代码

Activity

  1. public class TouchEventActivity extends Activity implements OnTouchListener {
  2. @Override
  3. protected void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. setContentView(R.layout.layout);
  6. findViewById(R.id.root).setTag("root");
  7. findViewById(R.id.ll_child).setTag("ll_child");
  8. findViewById(R.id.tv).setTag("tv");
  9. findViewById(R.id.tv_child).setTag("tv_child");
  10. findViewById(R.id.root).setOnTouchListener(this);
  11. findViewById(R.id.ll_child).setOnTouchListener(this);
  12. findViewById(R.id.tv).setOnTouchListener(this);
  13. findViewById(R.id.tv_child).setOnTouchListener(this);
  14. findViewById(R.id.tv_alert).setOnClickListener(v -> {
  15. Utils.TYPE = (Utils.TYPE + 1) % 6;
  16. Toast.makeText(this, "值为 " + Utils.TYPE, Toast.LENGTH_SHORT).show();
  17. });
  18. }
  19. @Override
  20. protected void onResume() {
  21. super.onResume();
  22. Toast.makeText(this, "值为 " + Utils.TYPE, Toast.LENGTH_SHORT).show();
  23. }
  24. @Override
  25. public boolean onTouch(View v, MotionEvent event) {
  26. Log.i("【bqt】", "onTouch--" + v.getTag() + "--" + Utils.getActionName(event));
  27. return false;
  28. }
  29. }

自定义 LinearLayout

  1. public class MyLinearLayout extends LinearLayout {
  2. public MyLinearLayout(Context context, AttributeSet attrs) {
  3. super(context, attrs);
  4. }
  5. @Override
  6. public boolean dispatchTouchEvent(MotionEvent event) {
  7. Log.i("【bqt】", "dispatchTouchEvent--" + getTag() + "--" + Utils.getActionName(event));
  8. return (getId() == R.id.ll_child && Utils.TYPE == 1) || super.dispatchTouchEvent(event);
  9. }
  10. @Override
  11. public boolean onInterceptTouchEvent(MotionEvent event) {
  12. Log.i("【bqt】", "onInterceptTouchEvent--" + getTag() + "--" + Utils.getActionName(event));
  13. return (getId() == R.id.ll_child && Utils.TYPE == 3) || super.onInterceptTouchEvent(event);
  14. }
  15. @Override
  16. public boolean onTouchEvent(MotionEvent event) {
  17. Log.i("【bqt】", "onTouchEvent--" + getTag() + "--" + Utils.getActionName(event));
  18. return (getId() == R.id.ll_child && Utils.TYPE == 4) || super.onTouchEvent(event);
  19. }
  20. }

自定义 TextView

  1. public class MyTextView extends AppCompatTextView {
  2. public MyTextView(Context context, AttributeSet attrs) {
  3. super(context, attrs);
  4. }
  5. @Override
  6. public boolean dispatchTouchEvent(MotionEvent event) {
  7. Log.i("【bqt】", "dispatchTouchEvent--TextView--" + getTag() + "--" + Utils.getActionName(event));
  8. return (getId() == R.id.tv_child && Utils.TYPE == 2) || super.dispatchTouchEvent(event);
  9. }
  10. @Override
  11. public boolean onTouchEvent(MotionEvent event) {
  12. Log.i("【bqt】", "onTouchEvent--" + getTag() + "--" + Utils.getActionName(event));
  13. return (getId() == R.id.tv_child && Utils.TYPE == 5) || super.onTouchEvent(event);
  14. }
  15. }

工具类

  1. public class Utils {
  2. public static int TYPE = 0;
  3. public static String getActionName(MotionEvent event) {
  4. switch (event.getAction()) {
  5. case ACTION_DOWN:
  6. return "按下";
  7. case ACTION_UP:
  8. return "松开";
  9. case ACTION_MOVE:
  10. return "移动";
  11. default:
  12. return "未知";
  13. }
  14. }
  15. }

补充

一些面试题

View的onTouchEvent方法,OnClickListerner的OnClick方法,OnTouchListener的onTouch方法,这三者的优先级如何?

onTouch > onTouchEvent > OnClick

如果子View和父ViewGroup的onTouchEvent都返回true,哪个控件的onTouchEvent会执行?

子View的。这种情况下,让父ViewGroup的onInterceptTouchEvent方法返回true即可让父ViewGroup的onTouchEvent执行。

如果某个view(不包括VG)处理事件的时候没有消耗down事件,会有什么结果?

假如一个view,在down事件来的时候他的onTouchEvent返回false, 那么这个down事件所属的事件序列,就是他后续的move和up都不会给他处理了。

注意:之所以不包括VG,绝不是因为对于后续的move和up,此view的父View的onTouchEvent会回调,而只是因为任何view所接收到的事件都是通过VG传递过来的。

一旦有事件传递给view(不包括VG),view的onTouchEvent一定会被调用吗?

一定会(一定要三思,否则多半会回答"不一定会")。

因为view本身没有onInterceptTouchEvent方法,所以只要事件来到view这里就一定会走onTouchEvent方法,并且默认都是返回true的,除非这个view是不可点击的。

PS:所谓不可点击就是clickablelongClickable同时为fale。

Button的clickable就是true,但是textview是false。

enable是否影响view的onTouchEvent返回值?

不影响

只要view的clickable和longClickable有一个为真,那么此view的onTouchEvent就返回true

requestDisallowInterceptTouchEvent 的作用?

可以在子元素中干扰父元素的事件分发

但是down事件干扰不了。

onTouchEvent和GestureDetector在什么时候用哪个比较好?

只有滑动需求的时候就用onTouchEvent

如果有双击、抛掷等行为的时候就用GestureDetector

滑动冲突问题如何解决?

要解决滑动冲突,其实主要的就是一个核心思想:你到底想让哪个 view 来响应你的滑动?

比如,从上到下滑,是哪个view来处理这个事件,从左到右呢?

业务需求想明白以后,解决的方法就是2个:外部拦截(父亲拦截)和内部拦截,基本上所有的滑动冲突都是这2种的变种,而且核心代码思想都一样。

外部拦截法

外部拦截法的思路就是重写父容器的onInterceptTouchEvent方法,子元素一般不需要做额外的处理。我们通常是对父View的onInterceptTouchEvent接收到的Move事件做一个过滤,当Move事件满足适当条件时(如持续若干时间或移动若干距离)会拦截掉,并返回子View一个Action_Cancel事件。这种方式比较简单且很容易让人理解。

伪代码:

  1. @Override
  2. public boolean onInterceptTouchEvent(MotionEvent event) {
  3. boolean intercepted = false;
  4. switch (event.getAction()) {
  5. case MotionEvent.ACTION_DOWN:
  6. intercepted = false;
  7. break;
  8. case MotionEvent.ACTION_MOVE:
  9. if (父容器需要点击事件) {
  10. intercepted = true;
  11. } else {
  12. intercepted = false;
  13. }
  14. break;
  15. case MotionEvent.ACTION_UP:
  16. intercepted = false;
  17. break;
  18. default:
  19. break;
  20. }
  21. return intercepted;
  22. }

在父容器的onInterceptTouchEvent方法中:

  • 对于ACTION_DOWN事件,父容器必须返回false,即不拦截ACTION_DOWN事件,这是因为一旦父容器拦截者这个事件,那么后续的ACTION_MOVE和ACTION_UP事件都会直接交由父容器处理,这个时候就没法传递给子元素了
  • 对于ACTION_UP事件,父容器也必须返回false,否则就会导致子元素无法接收到ACTION_UP事件,这个时候onClick事件就无法触发
  • 对于ACTION_MOVE事件,这个事件可以根据需要来决定是否拦截

内部拦截法

内部拦截法的思路就是父容器不拦截任何事件,所有事件都传递给子元素,如果子元素需要此事件就直接消耗掉,否则就交由父容器处理。我们需要重写子元素的dispatchTouchEvent方法,在其中调用getParent().requestDisallowInterceptTouchEvent(true),作用是告诉父view,这个触摸事件由我来处理,不要阻碍我。

伪代码:

  1. @Override
  2. public boolean dispatchTouchEvent(MotionEvent event) {
  3. switch (event.getAction()) {
  4. case MotionEvent.ACTION_DOWN:
  5. parent.requestDisallowInterceptTouchEvent(true);// 表示不拦截
  6. break;
  7. case MotionEvent.ACTION_MOVE:
  8. if (父容器需要点击事件) {
  9. parent.requestDisallowInterceptTouchEvent(false);// 表示拦截
  10. }
  11. break;
  12. case MotionEvent.ACTION_UP:
  13. break;
  14. default:
  15. break;
  16. }
  17. return super.dispatchTouchEvent(event);
  18. }

requestDisallowInterceptTouchEvent方法通过改变FLAG_DISALLOW_INTERCEPT标记位拦截事件,但是ACTION_DOWN事件不受这个标记位的控制

onTouch 和 onTouchEvent 的区别

对于View,我们可以通过重写onTouchEvent方法来处理Touch事件,也可以通过实现OnTouchListener的接口,然后在onTouch方法中达到同样的目的,这两种监听有什么区别呢?

这两个方法都是在View的dispatchTouchEvent中调用的,onTouch优先于onTouchEvent执行。如果在onTouch方法中通过返回true将事件消费掉,onTouchEvent将不会再执行。

另外需要注意的是,onTouch能够得到执行需要两个前提条件,第一mOnTouchListener的值不能为空,第二当前点击的控件必须是enable的。因此如果你有一个控件是非enable的,那么给它注册onTouch事件将永远得不到执行。对于这一类控件,如果我们想要监听它的touch事件,就必须通过在该控件中重写onTouchEvent方法来实现。

总结

  • 1、onTouchListeneronTouch方法优先级比onTouchEvent方法高,会先触发。
  • 2、假如onTouch方法返回false会接着触发onTouchEvent方法,反之onTouchEvent方法不会被调用。
  • 3、内置诸如click事件的实现等等都基于onTouchEvent,假如onTouch返回true,这些事件将不会被触发。

2017-10-14

事件分发机制 事件拦截 滑动冲突 MD的更多相关文章

  1. Android view 的事件分发机制

    1 事件的传递顺序是 Activity -> Window -> 顶层View touch 事件产生后,最先由 activity 的 dispatchTouchEvent 处理 /** * ...

  2. Android View的事件分发机制和滑动冲突解决方案

    这篇文章会先讲Android中View的事件分发机制,然后再介绍Android滑动冲突的形成原因并给出解决方案.因水平有限,讲的不会太过深入,只希望各位看了之后对事件分发机制的流程有个大概的概念,并且 ...

  3. 【朝花夕拾】Android自定义View篇之(七)Android事件分发机制(下)滑动冲突解决方案总结

    前言 转载请声明,转自[https://www.cnblogs.com/andy-songwei/p/11072989.html],谢谢! 前面两篇文章,花了很大篇幅讲解了Android的事件分发机制 ...

  4. Android事件分发机制浅谈(一)

    ---恢复内容开始--- 一.是什么 我们首先要了解什么是事件分发,通俗的讲就是,当一个触摸事件发生的时候,从一个窗口到一个视图,再到一个视图,直至被消费的过程. 二.做什么 在深入学习android ...

  5. Atitit View事件分发机制

    1. Atitit View事件分发机制 1. Atitit View事件分发机制1 1.1. 三个关键方法 dispatchTouchEvent onInterceptTouchEvent onTo ...

  6. Android查缺补漏(View篇)--事件分发机制

    事件分发机制是Android中非常重要的一个知识点,同时也是难点,相信到目前为止很多Android开发者对事件分发机制并没有一个非常系统的认识,当然也包括博主个人在内.可能在平时的开发工作中我们并没有 ...

  7. Android事件分发机制源码分析

    Android事件分发机制源码分析 Android事件分发机制源码分析 Part1事件来源以及传递顺序 Activity分发事件源码 PhoneWindow分发事件源码 小结 Part2ViewGro ...

  8. Android开发——事件分发机制详解

    0. 前言   转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52566965 深入学习事件分发机制,是为了解决在Android开发中 ...

  9. 【自己定义控件】android事件分发机制

    自己定义Viewgrou中我们或许会常常碰到这种情况,2个子控件的事件冲突导致滑动没实用了.滑动反应非常慢,点击没用了,要划非常多次才移动一点点等等.或许我们第一反应就是百度,google去搜索下答案 ...

随机推荐

  1. Nutch源码阅读进程5

    看nutch的源码仿佛就是一场谍战片,而构成这精彩绝伦的谍战剧情的就是nutch的每一个从inject->generate->fetch->parse->update的环节,首 ...

  2. Bzoj4558:分类讨论 计算几何 组合数学

    国际惯例的题面: 这题让我爆肝啦......这种计数显然容斥,正好不含任何坏点的我们不会算,但是我们能算至少含零个坏点的,至少含一个坏点的,至少含两个坏点的......所以最终的答案就是(至少含零个坏 ...

  3. HDU 4709 3-idiots FFT 多项式

    http://acm.hdu.edu.cn/showproblem.php?pid=4609 给一堆边,求这一堆边随便挑三个能组成三角形的概率. 裸fft,被垃圾题解坑了还以为很难. 最长的边的长度小 ...

  4. python3 开发面试题(面向对象)6.6

    """ 封装.继承.多态 1. 谈谈你对面向对象的理解? 2. Python面向对象中的继承有什么特点? 3. 面向对象深度优先和广度优先是什么? 4. 面向对象中sup ...

  5. hdu 5723 Abandoned country 最小生成树 期望

    Abandoned country 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5723 Description An abandoned coun ...

  6. Hadoop系列之(三):使用Cloudera部署,管理Hadoop集群

    1. Cloudera介绍 Hadoop是一个开源项目,Cloudera对Hadoop进行了商业化,简化了安装过程,并对hadoop做了一些封装. 根据使用的需要,Hadoop集群要安装很多的组件,一 ...

  7. JS本地存储信息的实现方式(localStorage 与 userData)

    详细介绍请看: http://www.cnblogs.com/beiyuu/archive/2011/07/20/js-localstorage-userdata.html 里面涉及到的 demo 代 ...

  8. Win10专业版永久激活方法

    自从升级安装了Windows10系统以后,我想很多朋友和我一样,想要激活Windows10系统,但是小编找了半天以后发现,很多激活工具都是批量激活的,也就是只有180天的使用时间,那么我们怎么永久激活 ...

  9. EditPlus(4.0.0.395)中文免激活绿色版

    EditPlus一套功能强大,可取代记事本的文字编辑器,拥有无限制的撤消与重做.英文拼字检查.自动换行.列数标记.搜寻取代.同时编辑多文件.全屏幕浏览功能.而它还有一个好用的功能,就是它有监视剪贴板的 ...

  10. 总结ASP.NET MVC视图页使用jQuery传递异步数据的几种方式

    在ASP.NET MVC的视图页向控制器传递异步数据,可能是数组,JavaScript对象,json,表单数据,等等. 关于数据,JavaScript对象有时候和json长得一模一样,有么有? var ...