OnTouch
OmOnTouchListener
OnTouchEvent

View的事件分发 :
    对于事件分发机制,举个简单的例子,在一个Activity中只有一个按钮,如果我们想给这个按钮注册一个点击事件,只需要调用setOnClickListener方法,这样在onClick方法里
    面写实现的代码,就可以在按钮被点击的时候执行.我们再给这个按钮添加一个touch事件,只需要调用setOnTouchListener方法,onTouch方法里能做的事情比onClick要多一
    些,比如判断手指按下、抬起、移动等事件。如果我两个事件都注册了,我之前做过一个实验,运行程序点击按钮的结果是onTouch是优先于onClick执行的,并且onTouch执行
    了两次,一次是ACTION_DOWN,一次是ACTION_UP(你还可能会有多次ACTION_MOVE的执行,如果你手抖了一下)。因此事件传递的顺序是先经过onTouch,再传递到onClick。
    onTouch方法是有返回值的,如果我们尝试把onTouch方法里的返回值改成true,再运行一次就会发现onClick方法不再执行了,这是因为onTouch方法返回true就认为这个事件
    被onTouch消费掉了,因而不会再继续向下传递。

1、为什么要有事件分发机制
    如果ViewGroupA里面包含一个ViewGroupB,ViewGroupB里面再包含一个view,
    当点击view的时候,为什么只有view相应事件,点击的也是A的区域。
    这就引发了事件分发机制

2、MotionEvent主要有几个事件类型、
    down
    move
    up

3、事件分发的主要方法
    分发事件:
        dispatchTouchEvent(View,ViewGroup:view 之间touch事件传递的入口函数 onInterceptTouchEvent:判断 touch 事件是否拦截 onTouchEvent:处理 touch 事件)
        如果返回true/false,则表示事件传递到这儿就终止了,不会继续分发
        也不会传给父级

拦截事件:onInterceptTouchEvent
        只有ViewGroup有这个方法,只有子类才需要拦截。返回true,表示拦截该事件
        就不会分发给子类。

消费事件:onTouchEvent
        Touch 事件 ACTIONDOWN, ACTIONUP ,ACTIONMOVE, ACTIONCANCLE
        返回true,这个事件被消费掉了,就不会再传给出去了。如果没有人消费掉,则最终
        会被当前的activity消耗掉,下次的move和up事件就不会在传下去了。

注意:
        一个down事件分发之后,还有回传的过程。因为一个事件分发包括down、move、
        up这个几个动作,当手指触碰到屏幕那一刻,首先分发down事件,事件分发完之
        后还要回传回去,然后继续从头开始分发,执行下一个move操作,知道执行完up
        事件,整个分发过程到此结束。

当自定义viewgroup时不会拦截down事件,一旦拦截,后边的move和up就不会再
        传递下去了。事件以后只会传给viewgroup这里。

事件一旦分发到view则默认一定会执行他的onTouchEvent分发
        父view把touch 事件传递给子view 处理,是调用了子view 的 dispatchTouchEvent 方法
        子view的 dispatchTouchEvent 方法把 touch 事件交给两个兄弟负责:
        mOnTouchListener.onTouch 方法
        onTouchEvent 方法
        先是让 onTouch 方法处理 touch 事件,如果 onTouch 方法消耗掉 touch 事件,那么 dispatchTouchEvent 方法直接返回 true;如果 onTouch 方法没有消耗掉
        touch 事件,那么调用 onTouchEvent 方法来处理 touch 事件,此时 dispachTouchEvent 方法的返回值,就靠 onTouchEvent 方法来决定。

列举:
    A包括B,B包括C(view)详解:
    1、点击c,c不消费事件
    当一个事件产生后,传递流程是  activity --> phoneWindow --> view
    当点击c的时候,事件从mainActivity的事件分发开始,然后去问b是否消费事件,然后将事件
    分发给B,事件到了B,他不拦截事件,先去问自己的孩子要不要消费事件,然后发给c,事件
    到了view,开始执行dispatchevent方法来决定是否消费事件。
    事件回传, c不消费事件,所以它开始回传,告诉B我不消费事件(view的onTouchEvent返回false),然
    后B才有权利决定是否消费该事件,这时开始执行onTouchEvent事件,B也不消费事件,所以
    onTouchEvent也返回false,事件继续传给A的onTouchEvent方法,由于A也不消费,最终扔给
    了mainActivity去消费。

2、点击C,view消费掉事件
    mainActivity一层一层往下传,到了view便开始执行onTouchEvent方法来决定是否消费该事件,
    由于view消费掉了这个事件,view的onTouchEvent便return false,B收到通知view消费了事
    件,所以就不会执行B的onTouchEvent事件,只能回传告诉A,view消费了事件,你没机会了。
    A收到return true后,就知道事件被消费了,所以他也return true,最终事件传给
    了mainActivity,由于事件被消费了,所以不会执行mainActivity的onTouchEvent方法,
    接下来执行Move事件,流程和之前的一样,重新开始执行。
    结论:onTouchEvent被view消费掉,A、B的onTouchEvent都不会执行。

3、点击B,但是B不消费事件。
    B和A都不消费事件,最终只能交给mainActivity了去消费了。
    view的mOnTouchListener.onTouch方法优先于view的onTouchEvent方法。
         onTouchEvent 方法主要实现了 3 个功能:
         1. 根据 touch 事件产生 click 事件,调用 onClickListener.onclick 方法
         2. 根据 touch 事件产生 press 状态的变化
         3. 根据 touch 事件产生 焦点分发
    
view和viewgroup对onTouchEvent事件的处理什么不同和联系?

代码说明:

请父级View不拦截touch事件:

1.解决SwipeLayout和ListView的触摸事件冲突问题
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mDownX = event.getRawX();
                    break;
                case MotionEvent.ACTION_MOVE:
                    float deltaX = event.getRawX() - mDownX;
                    if(Math.abs(deltaX) > mHelper.getTouchSlop()){
                        getParent().requestDisallowInterceptTouchEvent(true);//请父级View不拦截touch事件
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    mDownX = 0;
                    break;
            }
            try {
                mHelper.processTouchEvent(event);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return true;
        }

touch事件分发的三个问题:

1. onTouch和onTouchEvent有什么区别,又该如何使用?
        从源码中可以看出,这两个方法都是在View的dispatchTouchEvent中调用的,onTouch优先于onTouchEvent执行。如果在onTouch方法中通过返回true将事件消费掉,
        onTouchEvent将不会再执行。
        另外需要注意的是,onTouch能够得到执行需要两个前提条件,第一mOnTouchListener的值不能为空,第二当前点击的控件必须是enable的。因此如果我们有一个控件
        是非enable的,那么给它注册onTouch事件将永远得不到执行。对于这一类控件,如果我们想要监听它的touch事件,就必须通过在该控件中重写onTouchEvent方法来实
        现。

2. 为什么给ListView引入了一个滑动菜单的功能,ListView就不能滚动了?
        如果你阅读了http://blog.csdn.net/guolin_blog/article/details/8744400 滑动菜单的功能是通过给ListView注册了一个touch事件来实现的。如果我们在onTouch方
        法里处理完了滑动逻辑后返回true,那么ListView本身的滚动事件就被屏蔽了,自然也就无法滑动(原理同前面例子中按钮不能点击),因此解决办法就是在onTouch方法
        里返回false。

3. 为什么图片轮播器里的图片使用Button而不用ImageView?
        提这个问题的朋友可看看http://blog.csdn.net/guolin_blog/article/details/8769904 这篇文章。这篇文章里,在图片轮播器里使用Button,主要就是因为Button是  
        可点击的,而ImageView是不可点击的。如果想要使用ImageView,可以有两种改法。第一,在ImageView的onTouch方法里返回true,这样可以保证ACTION_DOWN之后的其
        它action都能得到执行,才能实现图片滚动的效果。第二,在布局文件里面给ImageView增加一个android:clickable="true"的属性,这样ImageView变成可点击的之后
         ,即使在onTouch里返回了false,ACTION_DOWN之后的其它action也是可以得到执行的。

ZHBJ中...
触摸事件的处理:
    我认为触摸事件的处理实质上就是重写控件的  
    dispatchTouchEvent(),
    onInterceptTouchEvent(),
    onTouchEvent()方法
    处理控件的分发,拦截,触摸的逻辑,用以达到我们想要的目的.以我之前做过的项目为例,
    其中比较难的有两个,一个是三次ViewPager嵌套,一个是ScrollView嵌套ViewPager再嵌套Viewpager和ListView

>>>>>>>
    你看这个项目,它就是有三次ViewPager嵌套    
    他的最外层界面其实是一个VIewPager(其实它也可以用Fragment来做,不过我考虑到他是要不断切换界面这点和ViewPager的特点很像于是就用VIewPager来做了),我重写了它
    的onTouchEvent()方法,只返回true,屏蔽了它的滑动事件,并且设置了切换界面不滑动的属性,
    这点比较有意思,同样实现相同的功能,

用ViewPager做我们就想屏蔽它的界面切换效果,用fragment来做又想自己给它添加一个界面切换的动画).然后把界面的切换交给了界面下方的四个单选按钮实现(这个功能的
    实现方法有很多,可以写四个TextView,然后drawableTop画上图片或者用线布局上面放ImageView下面放TextView实现都可以,只是考虑到功能需求是只能单选,和单选按钮的
    功能最为相似,用它做最简单,

所有我使用一个RadioGroup嵌套四个RadioButton并且设置Radiobutton的button属性为null取消单选按钮的圆圈,drawableTop画上图片,给图片和字体颜色设置选择器实现的)
    ,并且把它的拦截事件onInterceptTouchEvent()方法重写返回false,让它不拦截子View的触摸事件(这个方法在ViewGroup中实现都比较简单,都是直接返回false,不过ViewPa
     ger和ListView都重写了这个方法,做了大量的逻辑和判断).

其次,社区界面的发现和关注也是用ViewPager实现的,由于它的父控件的onInterceptTouchEvent()拦截方法已经被我重写并且返回false,所以它可接收到父控件传递过来的
    触摸事件并对其处理,所以我并没有对这层ViewPager做什么特殊的处理,直接使用了系统V4包里原生的ViewPager

然后这个ViewPager里面的布局实际是一个Listview,前面几个比较特殊的界面是作为头布局添加进去的,这个头布局以及listview的条目中都有VIewPager的存在,这种情况就
    比较复杂了,
    因为这种ViewPager有很多控件都和它争抢触摸事件,比如它的父控件,listview,于是我做了这样的处理,首先ViewPager肯定是上下滑动不了的,然后只要ViewPager不是最后
    一个条目,我左右滑动都可以切换当前ViewPager,如果是最后一个条目的话,我再向右滑就可以切换父控件的ViewPager.所以我就重写了它的dispatchTouchEvent方法(),(虽然
    这里只有父ViewPager两个条目,但是我还是按照有多数pager的情况下写的以防以后业务发生改变,增加了条目),如果不是上下滑动,第一个条目右滑,最后一个条目左滑,我请
    求父控件不阻拦其触摸事件,让这个ViewPager处理滑动事件否则就不让父控件不阻拦,让父控件走自己的逻辑.

而这个项目是我协助我朋友做的,它涉及到ScollView嵌套ViewPager,它这里面还用到了很多自定义控件

onTouch的更多相关文章

  1. [示例] Firemonkey OnTouch 多点触控应用

    说明:Firemonkey OnTouch 多点触控应用,可同时多指移动多个不同控件 原码下载:[原创]TestMultitouchMove_多点触控应用_by_Aone.zip 运行展示:

  2. 记录下帮助一位网友解决的关于android子控件的onTouch或onClick和父OnTouch 冲突的问题。

    前三天收到位网友的私信求助,问题大概如标题所示.具体是下面的情况,个人感觉,这个问题挺有趣,也会在实际项目开发中很常见.不想看前奏的请直接跳至解决方法. 问题原型: 父控件是自定义的 LinearLa ...

  3. Android Touch事件传递机制 一: OnTouch,OnItemClick(监听器),dispatchTouchEvent(伪生命周期)

      ViewGroup View  Activity dispatchTouchEvent 有 有 有 onInterceptTouchEvent 有 无 无 onTouchEvent 有 有 有 例 ...

  4. onTouch与onClick冲突解决方法

    view.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent ...

  5. Android View的onTouchEvent和OnTouch区别

    还是以自定义的TestButton为例. 我们可以通过重写onTouchEvent方法来处理诸如down move up的消息: public class TestButton extends But ...

  6. Android中处理OnClick和OnTouch方法冲突的解决方案

    目前想到的最好的解决方法,大家有更好的欢迎告知. 问题:在一个view中有一个按钮,要求可以通过点按移动这个按钮,同时单纯的点击而不移动这个按钮的话可以跳转到新的Activity. 遇到的困难:按钮的 ...

  7. Android onTouch事件传递机制

    Android onTouch事件介绍: Android的触摸事件:onClick, onScroll, onFling等等,都是由许多个Touch组成的.其中Touch的第一个状态肯定是ACTION ...

  8. onTouch和onTouchEvent

    public boolean dispatchTouchEvent(MotionEvent event) { if (mOnTouchListener != null && mOnTo ...

  9. onTouch事件试验(覆写onTouchEvent方法,同时设置onTouchListener)

    xml布局文件 <</span>RelativeLayout xmlns:android="http://schemas.android.com/apk/res/andro ...

  10. android onclick onLongClick ontouch dispatchTouchEvent onInterceptTouchEvent

    android onclick onLongClick ontouch dispatchTouchEvent onInterceptTouchEvent 按ACTION_DOWN -> onLo ...

随机推荐

  1. 翻转数字最后n位

    #include<stdio.h> int turn_n(int ,int); int main(void) { ,b=; printf("%x\n%d\n%x\n", ...

  2. C语言 · 三角形

    算法提高 12-1三角形   时间限制:1.0s   内存限制:256.0MB      问题描述 为二维空间中的点设计一个结构体,在此基础上为三角形设计一个结构体.分别设计独立的函数计算三角形的周长 ...

  3. 基于Discuz的原生态MVC框架Uxf

    前言 国内大量网站在使用Discuz程序,当然,大多数网站只将其作为一款论坛程序,少量的将其作为一款完整的社区程序.因此,授权不授权的情况撇开不谈,很多人都会基于该款程序进行二次开发. Discuz二 ...

  4. Nginx实战系列之功能篇----后端节点健康检查(转)

    公司前一段对业务线上的nginx做了整理,重点就是对nginx上负载均衡器的后端节点做健康检查.目前,nginx对后端节点健康检查的方式主要有3种,这里列出:   1.ngx_http_proxy_m ...

  5. VS2010在C#头文件中添加文件注释的方法(转)

    步骤: 1.VS2010 中找到(安装盘符以D盘为例)D:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ItemTempl ...

  6. java- Servlet-session

    Servlet 相关:http://blog.csdn.net/ggGavin/article/category/2134213 Servlet——Session(1)之基础知识 Servlet——S ...

  7. win7配置ftp服务器

    1.安装FTP,打开控制面板,找到程序和功能-->打开或者关闭windows功能,在列表中,展开internet信息服务,勾选FTP服务器,展开WEB管理工具,勾选IIS管理控制台,然后点击确定 ...

  8. UML总结--总体架构

    架构图(一): 架构图(二): 转自:http://blog.csdn.net/lsh6688/article/details/5931706

  9. C++中前置声明的应用与陷阱

    前置声明的使用 有一定C++开发经验的朋友可能会遇到这样的场景:两个类A与B是强耦合关系,类A要引用B的对象,类B也要引用类A的对象.好的,不难,我的第一直觉让我写出这样的代码: // A.h #in ...

  10. 测试x264编码器的低延时编码和非延时编码

    最近在学x264的编码,经过大量的测试,编码1080P的视频,编码10000帧数据. 在设置为低延时编码的时候: 编码线程0,一帧耗时:7.000000 ms.编码线程0,一帧耗时:8.000000 ...