1.事件分发:public boolean dispatchTouchEvent(MotionEvent ev)

Touch 事件发生时 Activity 的 dispatchTouchEvent(MotionEvent ev) 方法会以隧道方式(从根元素依次往下传递直到最内层子元素或在中间某一元素中由于某一条件停止传递)将事件传递给最外层 View 的 dispatchTouchEvent(MotionEvent ev) 方法,并由该 View 的 dispatchTouchEvent(MotionEvent ev) 方法对事件进行分发。dispatchTouchEvent 的事件分发逻辑如下:

如果 return true,事件会分发给当前 View 并由 dispatchTouchEvent 方法进行消费,同时事件会停止向下传递;
如果 return false,事件分发分为两种情况:
如果当前 View 获取的事件直接来自 Activity,则会将事件返回给 Activity 的 onTouchEvent 进行消费;
如果当前 View 获取的事件来自外层父控件,则会将事件返回给父 View 的 onTouchEvent 进行消费。
如果返回系统默认的 super.dispatchTouchEvent(ev),事件会自动的分发给当前 View 的 onInterceptTouchEvent 方法。

2.事件拦截:public boolean onInterceptTouchEvent(MotionEvent ev)

在当前  View 的 dispatchTouchEvent(MotionEvent ev) 方法返回系统默认的 super.dispatchTouchEvent(ev) 情况下,事件会自动的分发给当前 View 的 onInterceptTouchEvent 方法。onInterceptTouchEvent 的事件拦截逻辑如下:

如果 onInterceptTouchEvent 返回 true,则表示将事件进行拦截,并将拦截到的事件交由当前 View 的 onTouchEvent 进行处理;
如果 onInterceptTouchEvent 返回 false,则表示将事件放行,当前 View 上的事件会被传递到子 View 上,再由子 View 的 dispatchTouchEvent 来开始这个事件的分发,如果当前事件没有点击在子View上而是在当前View其他空白区域,则发给当前 View 的 onTouchEvent 进行处理;
如果 onInterceptTouchEvent 返回super.onInterceptTouchEvent(ev)和返回false的处理逻辑一样。

3.事件响应:public boolean onTouchEvent(MotionEvent ev)

在 dispatchTouchEvent 返回 super.dispatchTouchEvent(ev) 并且 onInterceptTouchEvent 返回 true  或者由子View 的 onTouchEvent返回false的情况下 onTouchEvent 会被调用。onTouchEvent 的事件响应逻辑如下:

如果事件传递到当前 View 的 onTouchEvent 方法,而该方法返回了 false,那么这个事件会从当前 View 向上传递,并且都是由上层 View 的 onTouchEvent 来接收,如果传递到上面的 onTouchEvent 也返回 false,这个事件就会“消失”,而且接收不到下一次事件。

如果返回了 true 则会接收并消费该事件,如果没有其他特殊情况,下次事件不经过onInterceptTouchEvent(MotionEvent ev)。
如果返回 super.onTouchEvent(ev) 默认处理事件的逻辑和返回 false 时相同。

OnTouchListener,OnClickListener和OnLongClickListener的关系

在OnTouchListener事件里有MotionEvent.ACTION_DOWN,MotionEvent.ACTION_UP和MotionEvent.ACTION_MOVE三个事件,我们在这里只讨论MotionEvent.ACTION_DOWN,MotionEvent.ACTION_UP,与MOVE无关。在下面的文章中我们简称MotionEvent.ACTION_DOWN为TouchDown,简称MotionEvent.ACTION_UP为TouchUp。我们还知道Android有消化事件这个概念,在setOnTouchListener函数中如果是TouchDown我们返回true,在下文中我们称消化了TouchDown,返回false则没消化,TouchUp同理。

下面我们说明关系和证明(在用程序证明时每次运行都以 程序----操作----结果的顺序给出)。

1)OnTouchListener和OnClickListener的关系

关系:产生OnClick事件的条件(充要条件)是;TouchDown和TouchUp事件都没有被消化。事件处理的过程是:先处理TouchDown,之后处理TouchUp,如果这两个事件都没被消化,则处理OnClick事件。

程序结果:由于这个关系比较简单就不上图了。程序分4种情况分别为:

a)程序:消化TouchDown,不消化TouchUp------操作:单击按钮------结果:不产生OnClick事件

b)程序:不消化TouchDown,消化TouchUp------操作:单击按钮------结果:不产生OnClick事件

c)程序:消化TouchDown,消化TouchUp------操作:单击按钮------结果:不产生OnClick事件

d)程序:不消化TouchDown,不消化TouchUp----操作:单击按钮----结果:产生OnClick事件

2)OnTouchListener和OnLongClickListener的关系

关系:产生OnLongClick事件的条件(充要条件)是;在产生TouchDown事件,并且该TouchDown没有被消化,之后500毫秒内没有响应到TouchUp,则产生OnLongClick事件。

程序结果:对运行情况按TouchDown是否被消化,TouchUp是否被消化,我的操作是长按还是短按可以分为8种运行情况,在这里就不一一列举了,按我们的需要进行分类列举。

a)如果消化TouchDown,按照前面给出的关系,则不可能产生OnLongClick事件。事实是同过我的测试,在这个条件下我对TouchUp是否被消化和操作是长按还是短按4种情况都进行测试,结果都是不产生OnLongClick事件。

b)不消化TouchDown,下面对TouchUp是否被消化又分为两种情况:

bx)不消化TouchDown,不消化TouchUp,对长按和短按分别测试,根据前面给出的关系我们可以推断出长按产生OnLongClick,短按不产生OnLongClick

bx1)程序:不消化TouchDown,不消化TouchUp,----操作:短时间单击按钮----结果:不产生OnLongClick事件

bx2)程序:不消化TouchDown,不消化TouchUp,----操作:长时间单击按钮----结果:产生OnLongClick事件

测试结果满足我们的推断。

by)不消化TouchDown,消化TouchUp,对长按和短按分别测试,根据前面给出的关系我们可以推断出不论长按还是短按,都会产生OnLongClick事件。

by1)程序:不消化TouchDown,消化TouchUp,----操作:短时间单击按钮----结果:产生OnLongClick事件

by2)程序:不消化TouchDown,消化TouchUp,----操作:长时间单击按钮----结果:产生OnLongClick事件

测试结果满足我们的推断。

测试完全符合我们的预期,所以前面给出的关系是对的。

补充:OnClickListener和OnLongClickListener的关系,根据汉语的意思了,可能会感觉到这两个事件会有关系。但是事实是他们之间的关系是没有关系,前面已经给出这两个事件产生的条件了,而且是充分条件,这足已说明这两个事件没关系了。

scrollview嵌套HorizontalScrollView卡顿现象解决

开发中经验会遇到滑动里面嵌入滑动的问题,但是这种情况下触摸事件就会发生冲突。导致滑动非常卡,甚至出现程序停止响应。这种情况下我们一般需要重写view。下面给出重新scrollview的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class CustomScrollView extends ScrollView {  
    private GestureDetector mGestureDetector;  
    View.OnTouchListener mGestureListener;  
     
    public CustomScrollView(Context context, AttributeSet attrs) {  
        super(context, attrs);  
        mGestureDetector = new GestureDetector(new YScrollDetector());  
        setFadingEdgeLength(0);  
    }  
     
    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) {  
        return super.onInterceptTouchEvent(ev) && mGestureDetector.onTouchEvent(ev);  
    }  
     
    // Return false if we're scrolling in the x direction    
    class YScrollDetector extends SimpleOnGestureListener {  
        @Override 
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {  
            if(Math.abs(distanceY) > Math.abs(distanceX)) {  
                return true;  
            }  
            return false;  
        }  
    }  

Android 编程下Touch 事件的分发和消费机制和OnTouchListener,OnClickListener和OnLongClickListener的关系的更多相关文章

  1. Android 编程下 Touch 事件的分发和消费机制

    Android 中与 Touch 事件相关的方法包括:dispatchTouchEvent(MotionEvent ev).onInterceptTouchEvent(MotionEvent ev). ...

  2. Android 编程下Touch 事件的分发和消费机制

    1.事件分发:public boolean dispatchTouchEvent(MotionEvent ev) Touch 事件发生时 Activity 的 dispatchTouchEvent(M ...

  3. Android事件分发机制(一) Touch 事件的分发和消费机制

    Android 中与 Touch 事件相关的方法包括:dispatchTouchEvent(MotionEvent ev).onInterceptTouchEvent(MotionEvent ev). ...

  4. Touch 事件的分发和消费机制

    Android 中与 Touch 事件相关的方法包括:dispatchTouchEvent(MotionEvent ev).onInterceptTouchEvent(MotionEvent ev). ...

  5. 事件之Touch 事件的分发和消费机制

    Android 中与 Touch 事件相关的方法包括:dispatchTouchEvent(MotionEvent ev).onInterceptTouchEvent(MotionEvent ev). ...

  6. touch事件的分发和消费机制

    Android 中与 Touch 事件相关的方法包括:dispatchTouchEvent(MotionEvent ev).onInterceptTouchEvent(MotionEvent ev). ...

  7. Android中的Touch事件

    Android中的Touch事件处理 主要内容 Activity或View类的onTouchEvent()回调函数会接收到touch事件. 一个完整的手势是从ACTION_DOWN开始,到ACTION ...

  8. 通俗理解Android事件分发与消费机制

    深入:Android Touch事件传递机制全面解析(从WMS到View树) 通俗理解Android事件分发与消费机制 说起Android滑动冲突,是个很常见的场景,比如SliddingMenu与Li ...

  9. View,ViewGroup的Touch事件的分发机制

    原帖地址:http://blog.csdn.net/xiaanming/article/details/21696315 ViewGroup的事件分发机制 我们用手指去触摸Android手机屏幕,就会 ...

随机推荐

  1. shell 脚本中的入参获取与判断

    1.获取shell脚本的入参个数: $# 2.获取shell脚本的第n个入参的字符个数/字符串长度(注意这里的n需要替换为具体的数字,如果这个数字超过实际的入参个数,结果为0): ${#n}

  2. strings、strconv:让你高效的处理字符串

    strings包 strings.HasPrefix(s, prefix string) bool 判断字符串s是否以prefix开头.类似于python中的startswith. package m ...

  3. RHEL6中LVM逻辑卷管理

    1.LVM 基本术语   物理卷(physical volume):物理卷在逻辑卷管理中处于最底层,它可以是实际物理硬盘上的分区,也可以是整个物理硬盘.   卷组(Volume Group):卷组建立 ...

  4. centos7 Keepalived + Haproxy + MySQL pxc5.6

    拓扑图 应用通过 VIP 连接到 Haproxy,Haproxy 通过http代理分发请求到后端 3 台 MySQL pxc. Keepalived 可以有效防止 Haproxy 单点故障. MySQ ...

  5. linux发行版及版本号

    1991年8月:Linus Torvalds宣布成立Linux            遵行GPL: Kernel:底层监控程序又叫通用程序,即我们所说的操作系统    Kernel的作用:       ...

  6. win 10.0.17134.915 版本无法更新处理方法

    用CMD(以管理员方式运行)分别运行:1. Dism /Online /Cleanup-Image /RestoreHealth2.   sfc /scannow 注意:第2步比较慢,有进度条,请耐心 ...

  7. 小程序UI设计(3)-符合视觉规范-列表视觉规范

    上一篇我们介绍了字体规范,此贴介绍一下在列表中如何组合使用.下图是微信官方的要求   在工具中通过拖拽组件可以制作出一样的效果拖拽一个WViewRow.这个组件是小程序的view,flex-direc ...

  8. postgresql 锁表查询语句

    1 查找锁表的pid select pid from pg_locks l join pg_class t on l.relation = t.oid where t.relkind = 'r' an ...

  9. centos7 nginx 代理

    2019/06/05 15:00:23 [crit] 4332#4332: *1 connect() to 127.0.0.1:8080 failed (13: Permission denied) ...

  10. grunt-contrib-concat 合并任意文件

    grunt-contrib-concat可用于合并任意文件(css\js\txt等) 安装插件:npm install grunt-contrib-concat --save-dev 参数: sepa ...