android 触摸事件传递机制

来源:互联网 发布:淘宝买衣服怎么看质量 编辑:程序博客网 时间:2024/04/29 03:33

先运行拦截事件oninterceptTouchEvent(),再运行触摸事件onTouchEvent。
点击事件从上层到下层,事件回馈从下层到上层。
Android系统中的每个View的子类都具有下面三个和TouchEvent处理密切相关的方法:
1)publicboolean dispatchTouchEvent(MotionEvent ev) 这个方法用来分发TouchEvent
2)publicboolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent
3)publicboolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent。
当TouchEvent发生时,首先Activity将TouchEvent事件通过dispatchTouchEvent方法传递给ViewGroup
1,ViewGroup通过dispatchTouchEvent方法传递给interceptTouchEvent:
(1)如果interceptTouchEvent返回true ,则交给这个ViewGroup的onTouchEvent处理。
(2)如果interceptTouchEvent返回false,则交给子View的 dispatchTouchEvent方法处理。
2,事件传递到子view 的 dispatchTouchEvent方法中,通过该方法传递到当前View的onTouchEvent方法中:
(1)如果onTouchEvent返回true,那么这个事件就会止于该view。
(2)如果onTouchEvent返回false ,那么这个事件会从这个子view 往上传递,而且都是传递到父View的onTouchEvent 来接收。 (3)如果传递到ViewGroup的 onTouchEvent 也返回false 的话,则继续传递到Activity的onTouchEvent中,如果还是false,则这个事件就会“消失“;
事件向上传递到中间的任何onTouchEvent方法中,如果返回true,则事件被消费掉,不会再传递。
在默认的onInterceptTouchEvent()方法和onTouchEvent()中返回值都是false。
代码示例:用两个LinearLayout模拟父View和子View:
布局xml:父view是FirstLayout,子View是SecondLayout。

<?xml version="1.0" encoding="utf-8"?><com.cindy.usingtouchevent.FirstLayout    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"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.cindy.usingtouchevent.MainActivity">    <com.cindy.usingtouchevent.SecondLayout        android:layout_width="match_parent"        android:layout_height="match_parent">    </com.cindy.usingtouchevent.SecondLayout></com.cindy.usingtouchevent.FirstLayout>

FirstLayout.java

package com.cindy.usingtouchevent;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.LinearLayout;/** * Created by yub on 2016/10/9. */public class FirstLayout extends LinearLayout{    public FirstLayout(Context context, AttributeSet attrs) {        super(context, attrs);    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        switch(ev.getAction()){            case MotionEvent.ACTION_DOWN:                showLog("onInterceptTouchEvent down");                break;            case MotionEvent.ACTION_MOVE:                showLog("onInterceptTouchEvent move");                break;            case MotionEvent.ACTION_UP:                showLog("onInterceptTouchEvent up");                break;            default:break;        }//        return super.onInterceptTouchEvent(ev);        **return false;**    } @Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {    showLog("dispatchTouchEventok");    returnsuper.dispatchTouchEvent(ev);}    @Override    public boolean onTouchEvent(MotionEvent event) {        switch(event.getAction()){            case MotionEvent.ACTION_DOWN:                showLog("onTouchEvent down");                break;            case MotionEvent.ACTION_MOVE:                showLog("onTouchEvent move");                break;            case MotionEvent.ACTION_UP:                showLog("onTouchEvent up");                break;            default:break;        }        **return false;**    }    private void showLog(String str){        System.out.println("FirstLinearLayout:"+str);    }}

SecondLayout.java

public class SecondLayout extends LinearLayout {    public SecondLayout(Context context,AttributeSetattrs) {        super(context, attrs);    }    @Override    public booleanonInterceptTouchEvent(MotionEventev) {        switch(ev.getAction()){           case MotionEvent.ACTION_DOWN:               showLog("onInterceptTouchEventdown");               break;           case MotionEvent.ACTION_MOVE:               showLog("onInterceptTouchEventmove");               break;           case MotionEvent.ACTION_UP:               showLog("onInterceptTouchEventup");               break;           default:break;        }       **return true;**    }    @Override    public boolean dispatchTouchEvent(MotionEventev){       showLog("dispatchTouchEventok");        return super.dispatchTouchEvent(ev);    }    @Override    public boolean onTouchEvent(MotionEventevent) {       switch(event.getAction()){           case MotionEvent.ACTION_DOWN:               showLog("onTouchEventdown");               break;           case MotionEvent.ACTION_MOVE:               showLog("onTouchEventmove");               break;           case MotionEvent.ACTION_UP:               showLog("onTouchEventup");               break;           default:break;        }        **return true;**    }    private void showLog(String str){       System.out.println("SecondLinearLayout:"+ str);    }}

MainActivity.java

public class MainActivity extends AppCompatActivity {    private TextView tv;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }}

Log分析
请注意代码中用**标注的返回值。
First dispatchTouchEvent();———-A事件
First onInteruptTouchEvent();————B事件
First TouchEvent();————C事件
Second dispatchTouchEvent();———–D事件
Second onInteruptTouchEvent();————-E事件
Second TouchEvent();—————F事件

1.ABC均返回true,此时log如下:
10-11 23:31:35.750 12434-12434/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:dispatchTouchEvent ok
事件不再分发。

2.A返回false,BC均返回true,log如下:
10-11 23:33:00.995 14165-14165/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:dispatchTouchEvent ok
10-11 23:33:00.995 14165-14165/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:onInterceptTouchEvent down
10-11 23:33:00.995 14165-14165/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:onTouchEvent down
10-11 23:33:01.010 14165-14165/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:dispatchTouchEvent ok
10-11 23:33:01.010 14165-14165/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:onTouchEvent up
可以看出:首先执行A事件,传给拦截事件,传给触摸事件,再次分发,传给触摸事件,up后事件完成。

3.AC返回false,B返回true,log如下:
10-11 23:35:57.580 16818-16818/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:dispatchTouchEvent ok
10-11 23:35:57.580 16818-16818/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:onInterceptTouchEvent down
10-11 23:35:57.580 16818-16818/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:onTouchEvent down
可以看出:首先执行分发事件,传给拦截事件,传给触摸事件,触摸事件返回false,事件消失。

4.AB返回false,C返回true。此时事件会向子View传递。D返回true。log如下:
10-11 23:40:32.295 21737-21737/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:dispatchTouchEvent ok
10-11 23:40:32.295 21737-21737/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:onInterceptTouchEvent down
10-11 23:40:32.295 21737-21737/com.cindy.usingtouchevent I/System.out:SecondLinearLayout:dispatchTouchEvent ok
10-11 23:40:32.350 21737-21737/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:dispatchTouchEvent ok
10-11 23:40:32.350 21737-21737/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:onInterceptTouchEvent up
可以看出:父分发–父拦截down–子分发–父分发–父拦截up,事件结束。

5.AB返回false,C返回true。D返回false,E,F返回true.Log如下:
10-11 23:44:11.895 25623-25623/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:dispatchTouchEvent ok
10-11 23:44:11.895 25623-25623/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:onInterceptTouchEvent down
10-11 23:44:11.895 25623-25623/com.cindy.usingtouchevent I/System.out:SecondLinearLayout:dispatchTouchEvent ok
10-11 23:44:11.895 25623-25623/com.cindy.usingtouchevent I/System.out:SecondLinearLayout:onInterceptTouchEvent down
10-11 23:44:11.895 25623-25623/com.cindy.usingtouchevent I/System.out:SecondLinearLayout:onTouchEvent down
10-11 23:44:11.900 25623-25623/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:dispatchTouchEvent ok
10-11 23:44:11.900 25623-25623/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:onInterceptTouchEvent up
10-11 23:44:11.900 25623-25623/com.cindy.usingtouchevent I/System.out:SecondLinearLayout:dispatchTouchEvent ok
10-11 23:44:11.900 25623-25623/com.cindy.usingtouchevent I/System.out:SecondLinearLayout:onTouchEvent up
可以看出:父分发–父拦截down-子分发-子拦截down-子触摸down-子触摸up,事件结束。

6.AB返回false,C返回true。DE返回false,F返回true。log如下:
10-11 23:47:27.385 28570-28570/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:dispatchTouchEvent ok
10-11 23:47:27.390 28570-28570/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:onInterceptTouchEvent down
10-11 23:47:27.390 28570-28570/com.cindy.usingtouchevent I/System.out:SecondLinearLayout:dispatchTouchEvent ok
10-11 23:47:27.390 28570-28570/com.cindy.usingtouchevent I/System.out:SecondLinearLayout:onInterceptTouchEvent down
10-11 23:47:27.390 28570-28570/com.cindy.usingtouchevent I/System.out:SecondLinearLayout:onTouchEvent down
10-11 23:47:27.430 28570-28570/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:dispatchTouchEvent ok
10-11 23:47:27.430 28570-28570/com.cindy.usingtouchevent I/System.out: FirstLinearLayout:onInterceptTouchEventup
10-11 23:47:27.430 28570-28570/com.cindy.usingtouchevent I/System.out:SecondLinearLayout:dispatchTouchEvent ok
10-11 23:47:27.430 28570-28570/com.cindy.usingtouchevent I/System.out:SecondLinearLayout:onTouchEvent up
可以看出:父分发-父拦截down-子分发down-子拦截down-子触摸down-子触摸up,事件结束。
由5.6得知,子拦截的返回值与事件传播没有关系。

7.AB返回false,C返回true。DEF都返回false,log如下:
10-11 23:59:47.725 3738-3738/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:dispatchTouchEvent ok
10-11 23:59:47.725 3738-3738/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:onInterceptTouchEvent down
10-11 23:59:47.725 3738-3738/com.cindy.usingtouchevent I/System.out:SecondLinearLayout:dispatchTouchEvent ok
10-11 23:59:47.725 3738-3738/com.cindy.usingtouchevent I/System.out:SecondLinearLayout:onInterceptTouchEvent down
10-11 23:59:47.725 3738-3738/com.cindy.usingtouchevent I/System.out:SecondLinearLayout:onTouchEvent down
10-11 23:59:47.725 3738-3738/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:onTouchEvent down
10-11 23:59:47.755 3738-3738/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:dispatchTouchEvent ok
10-11 23:59:47.755 3738-3738/com.cindy.usingtouchevent I/System.out:FirstLinearLayout:onTouchEvent up
可以看出:父分发–父拦截-子分发-子拦截-子触摸–传回父级触摸事件down–父触摸up-事件结束。

0 0
原创粉丝点击