zoukankan      html  css  js  c++  java
  • Android Touch事件传递机制具体解释 下

    尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38025165

    资源下载:http://download.csdn.net/detail/yuanzeyao2008/7660997


    在前一篇文章中,我主要解说了Android源代码中的Touch事件的传递过程,如今我想使用一个demo以及一个实例来学习一下Andorid中的Touch事件处理过程。

    在Android系统中。和Touch事件分发和处理紧密相关的三个函数例如以下:
    (1) public boolean dispatchTouchEvent(MotionEvent ev)
    (2) public boolean onInterceptTouchEvent(MotionEvent ev)
    (3) public boolean onTouchEvent(MotionEvent event)


    这三个方法我在前一篇文章中都对他们的源代码进行了分析:方法1主要是对Touch事件进行分发,方法2主要是对Touch事件进行拦截,方法3是对Touch事件进行处理

    这三个方法主要存在于ViewGroup,View,Activity中,详细情况例如以下图:


    ViewGroup

    View

    Activity

    dispatchTouchEvent

    onInterceptTouchEvent

    onTouchEvent


    以下我们就使用一个demo来看看这些方法的运行流程:
    自己定义一个类:MyLayoutFirst.java

    public class MyLayoutFirst extends LinearLayout
    {
      private static final String TAG = "MyLayoutFirst";
      public MyLayoutFirst(Context context, AttributeSet attrs)
      {
        super(context, attrs);
      }
      
      @Override
      public boolean onInterceptTouchEvent(MotionEvent ev)
      {
        Log.w("yzy", "MyLayoutFirst->onInterceptTouchEvent->"+MyUtils.getActionName(ev));
        return super.onInterceptTouchEvent(ev);
      }
      
      @Override
      public boolean onTouchEvent(MotionEvent event)
      {
        Log.e("yzy", "MyLayoutFirst->onTouchEvent->"+MyUtils.getActionName(event));
        return super.onTouchEvent(event);
      }
      
      @Override
      public boolean dispatchTouchEvent(MotionEvent ev)
      {
        Log.i("yzy", "MyLayoutFirst->dispatchTouchEvent->"+MyUtils.getActionName(ev));
        return super.dispatchTouchEvent(ev);
      }
      
    }

    自己定义一个类;MyLayoutSecond.java

    public class MyLayoutSecond extends LinearLayout
    {
      private static final String TAG = "MyLayoutSecond";
      public MyLayoutSecond(Context context, AttributeSet attrs)
      {
        super(context, attrs);
      }
      
      @Override
      public boolean onTouchEvent(MotionEvent event)
      {
        Log.e("yzy", "MyLayoutSecond->MyLayoutSecond->"+MyUtils.getActionName(event));
        return super.onTouchEvent(event);
      }
      
      @Override
      public boolean onInterceptTouchEvent(MotionEvent ev)
      {
        Log.w("yzy", "MyLayoutSecond->onInterceptTouchEvent->"+MyUtils.getActionName(ev));
        return super.onInterceptTouchEvent(ev);
      }
      
      @Override
      public boolean dispatchTouchEvent(MotionEvent ev)
      {
        Log.i("yzy", "MyLayoutSecond->dispatchTouchEvent->"+MyUtils.getActionName(ev));
        return super.dispatchTouchEvent(ev);
      }
    
     
    }

    增加到main_layout.xml中

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
       >
    
        <com.event.demo.MyLayoutFirst 
            android:id="@+id/layout_first"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#FF0000"
            >
            <com.event.demo.MyLayoutSecond
    	        android:id="@+id/layout_second"
    	        android:layout_width="320dip"
    	        android:layout_height="120dip"
    	        android:layout_gravity="center"
    	        android:background="#0000FF"
            >
            
        </com.event.demo.MyLayoutSecond>
        </com.event.demo.MyLayoutFirst>
    
    </RelativeLayout>

    MainActivity中增加onTouchEvent方法

    public class MainActivity extends Activity
    {
    
      @Override
      protected void onCreate(Bundle savedInstanceState)
      {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
      }
    
      @Override
      public boolean onCreateOptionsMenu(Menu menu)
      {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
      }
      
      @Override
      public boolean dispatchTouchEvent(MotionEvent ev)
      {
        Log.i("yzy", "MainActivity->dispatchTouchEvent->"+MyUtils.getActionName(ev));
        return super.dispatchTouchEvent(ev);
      }
      
      @Override
      public boolean onTouchEvent(MotionEvent event)
      {
        Log.e("yzy", "MainActivity->onTouchEvent->"+MyUtils.getActionName(event));
        return super.onTouchEvent(event);
      }
    }

    最后就一个工具类,用来将事件id转换为字符串。

    public class MyUtils
    {
      private static final String TAG = "MyUtils";
      public static String getActionName(MotionEvent event)
      {
        String name="";
        switch(event.getAction())
        {
          case MotionEvent.ACTION_DOWN:
            name="ACTION_DOWN";
            break;
          case MotionEvent.ACTION_MOVE:
            name="ACTION_MOVE";
            break;
          case MotionEvent.ACTION_UP:
            name="ACTION_UP";
            break;
        }
        return name;
      }
    }

    执行效果如图:



    当中蓝色部分是MyLayoutSecond.java ,红色部分是MyLayoutFirst.java
    如今我点击一下蓝色部分:执行结果如图:


    从图中能够看出,事件最先被Activity捕获,然后分发给 MyLayoutFirst,MyLayoutFirst首先调用自身的onInterceptTouchEvent推断是否将该事件拦截。因为默认返回是false,所以没有拦截,从而事件分发给了MyLayoutSecond,MyLayoutSecond相同通过dispatchTouchEvent分发出去。分发出去之前相同检查是否被拦截,默认都是没有被拦截的,可是因为MyLayoutSecond是没有子视图的,全部终于事件有自己处理。调用自身的onTouchEvent方法,因为该方法默认返回的是false,所以觉得此事件是没有被消费掉的,继续传递到了MyLayoutFirst中,相同也没有消费这个事件,终于传递到了Mainactivity,继续往后看发现后面的ACTION_MOVE和ACTION_UP并没有传入MyLayoutFirst和MyLayoutSecond,这是因为一旦某一个事件没有被处理,后面的事件是不会被分发的。所以ACTION_MOVE和ACTION_UP直接被MainActivity处理掉了。


    以下再看另外一种情况:

    MainActivity

    MyLayoutFirst

    MyLayoutSecond

    dispatchTouchEvent

    super.dispatchTouchEvent

    super.dispatchTouchEvent

    super.dispatchTouchEvent

    onInterceptTouchEvent

    --

    true

    super.onInterceptTouchEvent(ev)

    onTouchEvent

    super.onTouchEvent

    super.onTouchEvent

    super.onTouchEvent

    执行结果例如以下:


    从图中能够看出,事件传递到了MyLayoutFirst后没有分发到MyLayoutSecond。直接调用自身的onTouchEvent,因为返回的是false,导致事件没有消费,终于传递给了MainActivity,
    并且兴许事件也没有传递到MyLayoutFirst和MyLayoutSecond。直接被MainActivity处理


    第三种情况:

    MainActivity

    MyLayoutFirst

    MyLayoutSecond

    dispatchTouchEvent

    super.dispatchTouchEvent

    super.dispatchTouchEvent

    super.dispatchTouchEvent

    onInterceptTouchEvent

    --

    true

    super.onInterceptTouchEvent(ev)

    onTouchEvent

    super.onTouchEvent

    true

    super.onTouchEvent

    执行结果:


    和情况二不同的是MyLayoutFirst的onTouchEvent返回了true。也就是说MyLayoutFirst消费了此事件,所以ACTION_DOWN也没有再传给MainActivity,而且ACTION_MOVE和ACTION_UP
    均传给了MyLayoutFirst


    第四中情况:

    MainActivity

    MyLayoutFirst

    MyLayoutSecond

    dispatchTouchEvent

    super.dispatchTouchEvent

    super.dispatchTouchEvent

    super.dispatchTouchEvent

    onInterceptTouchEvent

    --

    super.onInterceptTouchEvent(ev)

    super.onInterceptTouchEvent(ev)

    onTouchEvent

    super.onTouchEvent

    super.onTouchEven

    true

    执行结果:


    发现全部的事件都是传递到了MyLayoutSecond后被消费了


    事实上还有非常多其它组合方式。大家假设又兴趣能够自己尝试改变每一个函数的返回值。查看打印结果,这里我就不一一列举了。。。。




    最后我会提供一个小demo演示怎样解决滑动冲突,背景例如以下:
    一个ViewPager里面包括两个Framgent,有一个Fragment里面有一个HorizontalListView ,怎样滑动冲突?
    我就贴出关键代码吧


    horizontal=(HorizontalListView)view.findViewById(R.id.hscroll);
        horizontal.setOnTouchListener(new OnTouchListener()
        {
          
          @Override
          public boolean onTouch(View arg0, MotionEvent event)
          {
            if(event.getAction()==MotionEvent.ACTION_DOWN)
            {
              parent.requestDisallowInterceptTouchEvent(true);
            }else if(event.getAction()==MotionEvent.ACTION_UP)
            {
              parent.requestDisallowInterceptTouchEvent(false);
            }
            return false;
          }
        });

    增加这段代码就能够避免滑动冲突了,至于为什么大家能够參考我的前曾经文章《Android Touch 事件传递机制具体解释 上》 这两个demo的样例我均会上传下载的

  • 相关阅读:
    Rpc简单入门
    对话Task
    对话线程
    译MassTransit 生产消息
    MassTransit 实现应用程序间交互
    译MassTransit 消息契约
    轻松理解AOP思想(面向切面编程)
    Elasticsearch 全教程
    Elasticsearch 教程--搜索
    Elasticsearch 教程--数据
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/6852873.html
Copyright © 2011-2022 走看看