• Android Touch系统简介(二):实例详解onInterceptTouchEvent与onTouchEvent的调用过程


    上一篇文章主要讲述了Android的TouchEvent的分发过程,其中有两个重要的函数:onInterceptTouchEvent和onTouchEvent,这两个函数可被重装以完成特定的逻辑。onInterceptTouchEvent的定义为于ViewGroup中,默认返回值为false,表示不拦截TouchEvent。onTouchEvent的定义位于View中,当ViewGroup要调用onTouchEvent时,会利用super.onTouchEvent。ViewGroup调用onTouchEvent默认返回false,表示不消耗touch事件,View调用onTouchEvent默认返回true,表示消耗了touch事件。考虑到onInterceptTouchEvent与onTouchEven在写UI的时候经常会用到,下面以一个例子来讲解一下。

    先创建一个类MyView,继承自View

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. public class MyView extends Button {  
    2.     private static final String TAG = MyView.class.getName();  
    3.   
    4.     public MyView(Context context){  
    5.         super(context);  
    6.     }  
    7.   
    8.     public MyView(Context context, AttributeSet attrs) {  
    9.         super(context, attrs);  
    10.     }  
    11.   
    12.     @Override  
    13.     public boolean onTouchEvent(MotionEvent event) {  
    14.         Log.d(TAG, "onTouchEvent.");  
    15.         LogUtil.logAction(event, TAG);  
    16.         return super.onTouchEvent(event);  
    17.     }  
    18. }  


    创建类MyLayout,继承自ViewGroup

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. public class MyLayout extends FrameLayout{  
    2.     private static final String TAG = MyLayout.class.getName();  
    3.   
    4.     public MyLayout(Context context) {  
    5.         super(context);  
    6.     }  
    7.   
    8.     public MyLayout(Context context, AttributeSet attributeSet) {  
    9.         super(context, attributeSet);  
    10.     }  
    11.   
    12.     @Override  
    13.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
    14.         Log.d(TAG, "onInterceptTouchEvent");  
    15.   
    16.         return super.onInterceptTouchEvent(ev);  
    17.     }  
    18.   
    19.     @Override  
    20.     public boolean onTouchEvent(MotionEvent event) {  
    21.         Log.d(TAG, "onTouchEvent.");  
    22.         LogUtil.logAction(event, TAG);  
    23.         return super.onTouchEvent(event);  
    24.     }  
    25. }  

    LogUtil.logAction()函数是用来打印MotionEvent的动作类型,代码如下:

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. public class LogUtil {  
    2.     public static void logAction(MotionEvent event, final String tag) {  
    3.         int action = event.getAction();  
    4.         switch(action) {  
    5.             case MotionEvent.ACTION_DOWN:  
    6.                 Log.d(tag, "action down");  
    7.                 break;  
    8.             case MotionEvent.ACTION_CANCEL:  
    9.                 Log.d(tag, "action cancel");  
    10.                 break;  
    11.             case MotionEvent.ACTION_UP:  
    12.                 Log.d(tag, "action up");  
    13.                 break;  
    14.             case MotionEvent.ACTION_MOVE:  
    15.                 Log.d(tag, "action move");  
    16.                 break;  
    17.             default:  
    18.                 Log.d(tag, "unknow action");  
    19.         }  
    20.     }  
    21. }  


    布局文件main.xml将MyView嵌套在MyLayout中,代码如下:

    [html] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <view android:layout_width="fill_parent"  
    2.       android:layout_height="fill_parent"  
    3.       class="com.example.AndroidTest.MyLayout" xmlns:android="http://schemas.android.com/apk/res/android"  
    4.       android:id="@+id/view">  
    5.     <com.example.AndroidTest.MyView  
    6.             android:layout_width="fill_parent"  
    7.             android:layout_height="wrap_content"  
    8.             android:text="hello" />  
    9.       
    10. </view>  

    MainActivity的代码如下:

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. public class MainActivity extends Activity {  
    2.     public static final String TAG = "TouchDemoActivity";  
    3.     @Override  
    4.     public void onCreate(Bundle savedInstanceState)  
    5.     {  
    6.         super.onCreate(savedInstanceState);  
    7.         setContentView(R.layout.main);  
    8.     }  
    9.   
    10. }  


    程序启动后,截图如下。

    下面分情况讨论程序的运行结果。

    1、MyLayout的onInterceptTouchEvent返回false,MyView的onTouchEvent返回true

    情况1:当点击蓝色框内的任意位置,只有MyLayout会接收事件,输出的Log如下:


    可以看出,touch事件最后会被MyLayout的onTouchEvent接收到。

    情况2: 点击红色框内的黑色区域,由于onInterceptTouchEvent()返回false,故MyView也能接收到touchEvent事件,输出的Log如下:

    可以看出,由于MyView的onTOuchEvent默认返回True,消耗了touch事件,MyLayout中的onTOuchEvent将不会被调用。

    当我们的手指按下黑色区域,停留几秒再抬起,得到的Log如下图:

    可以看出,第一个事件的类型为action down,最后一个为action up,中间的都是action move的类型,这正好符合上一篇文章介绍的Android的手势定义。

    2、MyLayout的onInterceptTouchEvent返回false,MyView的onTouchEvent返回false

    改写MyView中onTouchEvent的代码,令其返回false

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. @Override  
    2. public boolean onTouchEvent(MotionEvent event) {  
    3.     Log.d(TAG, "onTouchEvent.");  
    4.     LogUtil.logAction(event, TAG);  
    5.     return false;  
    6. }  


    由于MyView没有消耗touch事件,MyLayout的onTouchEvent将会被调用,打印的log如下:

    可以看出,touch的类型只为action down。

    3、MyLayout的onInterceptTouchEvent返回true

    改写MyLayout中的onInterceptTouchEvent代码,令其返回true

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. @Override  
    2. public boolean onInterceptTouchEvent(MotionEvent ev) {  
    3.     Log.d(TAG, "onInterceptTouchEvent");  
    4.   
    5.     return true;  
    6. }  

    由于MyLayout拦截了touch事件,MyView中的onTouchEvent将不会被调用,log如下:



    以上对Android的onInterceptTouchEvent和onTouchEvent的描述若有不妥之处,欢迎指正。

    本文参考的代码出自:两分钟彻底让你明白Android中onInterceptTouchEvent与onTouchEvent(图文)!,感谢作者的无私分享。

  • 相关阅读:
    mysql 的锁
    vsphere虚拟机连网
    三种响应式文字(废弃)
    学习笔记(六)
    优秀 H5 案例收集 vol.3(不定期更新)
    优秀 H5 案例收集 Vol.2(不定期更新)
    优秀 H5 案例收集 vol.1(不定期更新)
    手机调取摄像头问题(getUserMedia)
    ES6 随记(3.3)-- 数组的拓展
    input-file 部分手机不能拍照问题
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/5504180.html
Copyright © 2020-2023  润新知