Android触摸事件传递机制小记

来源:互联网 发布:php官方文档 编辑:程序博客网 时间:2024/06/03 21:52
  • 事件类型
  • API
  • 事件流程
  • 事件处理

事件类型

我们可以通过event.getAction()方法来获得Action的状态值。

事件 int public static final int ACTION_DOWN 0 public static final int ACTION_UP 1 public static final int ACTION_MOVE 2

API

Activity 作用 public boolean dispatchTouchEvent(MotionEvent ev) 事件分发 public boolean onTouchEvent(MotionEvent event) 事件消费 ViewGroup 作用 public boolean dispatchTouchEvent(MotionEvent ev) 事件分发 public boolean onInterceptTouchEvent(MotionEvent ev) 事件拦截 public boolean onTouchEvent(MotionEvent event) 事件消费 View 作用 public boolean dispatchTouchEvent(MotionEvent ev) 事件分发 public boolean onTouchEvent(MotionEvent event) 事件消费

事件流程

为了方便演示实现建好了几个类 //部分代码省略
- MainActivity
- ViewGroupOne
- ViewGroupTwo
- TestView

public class MainActivity extends AppCompatActivity {    public static final String TAG = "MainActivity";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        TextView testView= (TextView) findViewById(R.id.testview);        testView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Toast.makeText(MainActivity.this, "testview", Toast.LENGTH_SHORT).show();            }        });    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                Log.e(TAG, "onTouchEvent--->ACTION_DOWN");                break;            case MotionEvent.ACTION_MOVE:                Log.e(TAG, "onTouchEvent--->ACTION_MOVE");                break;            case MotionEvent.ACTION_UP:                Log.e(TAG, "onTouchEvent--->ACTION_UP");                break;        }        return super.onTouchEvent(event);    }    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                Log.e(TAG, "dispatchTouchEvent--->ACTION_DOWN");                break;            case MotionEvent.ACTION_MOVE:                Log.e(TAG, "dispatchTouchEvent--->ACTION_MOVE");                break;            case MotionEvent.ACTION_UP:                Log.e(TAG, "dispatchTouchEvent--->ACTION_UP");                break;        }//        return true;        return super.dispatchTouchEvent(ev);    }
public class ViewGroupOne extends RelativeLayout {    public static final String TAG = "ViewGroupOne";    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                Log.e(TAG, "dispatchTouchEvent--->ACTION_DOWN");                break;            case MotionEvent.ACTION_MOVE:                Log.e(TAG, "dispatchTouchEvent--->ACTION_MOVE");                break;            case MotionEvent.ACTION_UP:                Log.e(TAG, "dispatchTouchEvent--->ACTION_UP");                break;        }        return super.dispatchTouchEvent(ev);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                Log.e(TAG, "onTouchEvent--->ACTION_DOWN");                break;            case MotionEvent.ACTION_MOVE:                Log.e(TAG, "onTouchEvent--->ACTION_MOVE");                break;            case MotionEvent.ACTION_UP:                Log.e(TAG, "onTouchEvent--->ACTION_UP");                break;        }        return super.onTouchEvent(event);    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                Log.e(TAG, "onInterceptTouchEvent--->ACTION_DOWN");                break;            case MotionEvent.ACTION_MOVE:                Log.e(TAG, "onInterceptTouchEvent--->ACTION_MOVE");                break;            case MotionEvent.ACTION_UP:                Log.e(TAG, "onInterceptTouchEvent--->ACTION_UP");                break;        }        return super.onInterceptTouchEvent(ev);    }}
public class ViewGroupTwo extends RelativeLayout {    public static final String TAG = "ViewGroupTwo";    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                Log.e(TAG, "dispatchTouchEvent--->ACTION_DOWN");                break;            case MotionEvent.ACTION_MOVE:                Log.e(TAG, "dispatchTouchEvent--->ACTION_MOVE");                break;            case MotionEvent.ACTION_UP:                Log.e(TAG, "dispatchTouchEvent--->ACTION_UP");                break;        }        return super.dispatchTouchEvent(ev);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                Log.e(TAG, "onTouchEvent--->ACTION_DOWN");                break;            case MotionEvent.ACTION_MOVE:                Log.e(TAG, "onTouchEvent--->ACTION_MOVE");                break;            case MotionEvent.ACTION_UP:                Log.e(TAG, "onTouchEvent--->ACTION_UP");                break;        }        return super.onTouchEvent(event);    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                Log.e(TAG, "onInterceptTouchEvent--->ACTION_DOWN");                break;            case MotionEvent.ACTION_MOVE:                Log.e(TAG, "onInterceptTouchEvent--->ACTION_MOVE");                break;            case MotionEvent.ACTION_UP:                Log.e(TAG, "onInterceptTouchEvent--->ACTION_UP");                break;        }        return super.onInterceptTouchEvent(ev);    }
public class TestView extends TextView {    public static final String TAG = "TestView";    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                Log.e(TAG, "dispatchTouchEvent--->ACTION_DOWN");                getParent().requestDisallowInterceptTouchEvent(true);                break;            case MotionEvent.ACTION_MOVE:                Log.e(TAG, "dispatchTouchEvent--->ACTION_MOVE");                break;            case MotionEvent.ACTION_UP:                Log.e(TAG, "dispatchTouchEvent--->ACTION_UP");                break;        }        return super.dispatchTouchEvent(ev);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                Log.e(TAG, "onTouchEvent--->ACTION_DOWN");                break;            case MotionEvent.ACTION_MOVE:                Log.e(TAG, "onTouchEvent--->ACTION_MOVE");                break;            case MotionEvent.ACTION_UP:                Log.e(TAG, "onTouchEvent--->ACTION_UP");                break;        }        return super.onTouchEvent(event);    }}

这里写图片描述

上图1区域代表ViewGroupOne,2区域代表ViewGroupTwo ,TextView代表TestView
关系为One include Two include test

  • 不做任何处理
//触摸1E/MainActivity: dispatchTouchEvent--->ACTION_DOWNE/ViewGroupOne: dispatchTouchEvent--->ACTION_DOWNE/ViewGroupOne: onInterceptTouchEvent--->ACTION_DOWNE/ViewGroupOne: onTouchEvent--->ACTION_DOWNE/MainActivity: onTouchEvent--->ACTION_DOWNE/MainActivity: dispatchTouchEvent--->ACTION_MOVEE/MainActivity: onTouchEvent--->ACTION_MOVEE/MainActivity: dispatchTouchEvent--->ACTION_MOVEE/MainActivity: onTouchEvent--->ACTION_MOVEE/MainActivity: dispatchTouchEvent--->ACTION_UPE/MainActivity: onTouchEvent--->ACTION_UP//触摸2E/MainActivity: dispatchTouchEvent--->ACTION_DOWNE/ViewGroupOne: dispatchTouchEvent--->ACTION_DOWNE/ViewGroupOne: onInterceptTouchEvent--->ACTION_DOWNE/ViewGroupTwo: dispatchTouchEvent--->ACTION_DOWNE/ViewGroupTwo: onInterceptTouchEvent--->ACTION_DOWNE/ViewGroupTwo: onTouchEvent--->ACTION_DOWNE/ViewGroupOne: onTouchEvent--->ACTION_DOWNE/MainActivity: onTouchEvent--->ACTION_DOWNE/MainActivity: dispatchTouchEvent--->ACTION_MOVEE/MainActivity: onTouchEvent--->ACTION_MOVEE/MainActivity: dispatchTouchEvent--->ACTION_MOVEE/MainActivity: onTouchEvent--->ACTION_MOVEE/MainActivity: dispatchTouchEvent--->ACTION_UPE/MainActivity: onTouchEvent--->ACTION_UP//触摸TextView(设置了点击事件) E/MainActivity: dispatchTouchEvent--->ACTION_DOWN E/ViewGroupOne: dispatchTouchEvent--->ACTION_DOWN E/ViewGroupOne: onInterceptTouchEvent--->ACTION_DOWN E/ViewGroupTwo: dispatchTouchEvent--->ACTION_DOWN E/ViewGroupTwo: onInterceptTouchEvent--->ACTION_DOWN E/TestView: dispatchTouchEvent--->ACTION_DOWN E/TestView: onTouchEvent--->ACTION_DOWN E/MainActivity: dispatchTouchEvent--->ACTION_MOVE E/ViewGroupOne: dispatchTouchEvent--->ACTION_MOVE E/ViewGroupTwo: dispatchTouchEvent--->ACTION_MOVE E/TestView: dispatchTouchEvent--->ACTION_MOVE E/TestView: onTouchEvent--->ACTION_MOVE E/MainActivity: dispatchTouchEvent--->ACTION_MOVE E/ViewGroupOne: dispatchTouchEvent--->ACTION_MOVE E/ViewGroupTwo: dispatchTouchEvent--->ACTION_MOVE E/TestView: dispatchTouchEvent--->ACTION_MOVE E/TestView: onTouchEvent--->ACTION_MOVE E/MainActivity: dispatchTouchEvent--->ACTION_MOVE E/ViewGroupOne: dispatchTouchEvent--->ACTION_MOVE E/ViewGroupTwo: dispatchTouchEvent--->ACTION_MOVE E/TestView: dispatchTouchEvent--->ACTION_MOVE E/TestView: onTouchEvent--->ACTION_MOVE E/MainActivity: dispatchTouchEvent--->ACTION_MOVE E/ViewGroupOne: dispatchTouchEvent--->ACTION_MOVE E/ViewGroupTwo: dispatchTouchEvent--->ACTION_MOVE E/TestView: dispatchTouchEvent--->ACTION_MOVE E/TestView: onTouchEvent--->ACTION_MOVE E/MainActivity: dispatchTouchEvent--->ACTION_UP E/ViewGroupOne: dispatchTouchEvent--->ACTION_UP E/ViewGroupTwo: dispatchTouchEvent--->ACTION_UP E/TestView: dispatchTouchEvent--->ACTION_UP E/TestView: onTouchEvent--->ACTION_UPSo :在正常情况下    1.传递的顺序为dispatchTouchEvent--->onInterceptTouchEvent--->onTouchEvent    2.分发的层级为Activity--->ViewGroupOne--->ViewGroupTwo (从外向内)    3.分发事件类型的顺序为Down--->Move--->up    4.若下级视图没有消费事件,最终返回到最上层处理,若被消费则不返回上层
  • 处理分发
return true;//return super.dispatchTouchEvent(ev);1.当MainActivity dispatchTouchEvent返回true 无论触摸任何区域 E/MainActivity: dispatchTouchEvent--->ACTION_DOWN E/MainActivity: dispatchTouchEvent--->ACTION_MOVE E/MainActivity: dispatchTouchEvent--->ACTION_MOVE E/MainActivity: dispatchTouchEvent--->ACTION_UP2.当ViewGroupOne dispatchTouchEvent返回true 无论触摸任何区域 E/MainActivity: dispatchTouchEvent--->ACTION_DOWN E/ViewGroupOne: dispatchTouchEvent--->ACTION_DOWN E/MainActivity: dispatchTouchEvent--->ACTION_MOVE E/ViewGroupOne: dispatchTouchEvent--->ACTION_MOVE E/MainActivity: dispatchTouchEvent--->ACTION_UP E/ViewGroupOne: dispatchTouchEvent--->ACTION_UP3.当TestView dispatchTouchEvent返回true 触摸TextView(不会弹出土司) E/MainActivity: dispatchTouchEvent--->ACTION_DOWN E/ViewGroupOne: dispatchTouchEvent--->ACTION_DOWN E/ViewGroupOne: onInterceptTouchEvent--->ACTION_DOWN E/ViewGroupTwo: dispatchTouchEvent--->ACTION_DOWN E/ViewGroupTwo: onInterceptTouchEvent--->ACTION_DOWN E/TestView: dispatchTouchEvent--->ACTION_DOWN E/MainActivity: dispatchTouchEvent--->ACTION_MOVE E/ViewGroupOne: dispatchTouchEvent--->ACTION_MOVE E/ViewGroupTwo: dispatchTouchEvent--->ACTION_MOVE E/TestView: dispatchTouchEvent--->ACTION_MOVE E/MainActivity: dispatchTouchEvent--->ACTION_UP E/ViewGroupOne: dispatchTouchEvent--->ACTION_UP E/ViewGroupTwo: dispatchTouchEvent--->ACTION_UP E/TestView: dispatchTouchEvent--->ACTION_UP 触摸区域1 E/MainActivity: dispatchTouchEvent--->ACTION_DOWN E/ViewGroupOne: dispatchTouchEvent--->ACTION_DOWN E/ViewGroupOne: onInterceptTouchEvent--->ACTION_DOWN E/ViewGroupOne: onTouchEvent--->ACTION_DOWN E/MainActivity: onTouchEvent--->ACTION_DOWN E/MainActivity: dispatchTouchEvent--->ACTION_MOVE E/MainActivity: onTouchEvent--->ACTION_MOVE E/MainActivity: dispatchTouchEvent--->ACTION_MOVE E/MainActivity: onTouchEvent--->ACTION_MOVE E/MainActivity: dispatchTouchEvent--->ACTION_UP E/MainActivity: onTouchEvent--->ACTION_UPSo:得出的结论是   1.当dispatchTouchEvent 返回true的时候不会往下执行任何事件(因为最先调用分发)   2.当这个层级的dispatchTouchEvent 返回true的时候 如果点击到本层级或者下层级,不会执行onTouchEvent,上层级正常


  • 处理拦截

ViewGroup作为容器,它有特有的一个方法,onInterceptTouchEvent,顾名思义,这个方法可以拦截容器内的层级执行
return true;//return super.onInterceptTouchEvent(ev); 将ViewGroupOne返回true//触摸任何区域 E/MainActivity: dispatchTouchEvent--->ACTION_DOWN E/ViewGroupOne: dispatchTouchEvent--->ACTION_DOWN E/ViewGroupOne: onInterceptTouchEvent--->ACTION_DOWN E/ViewGroupOne: onTouchEvent--->ACTION_DOWN E/MainActivity: onTouchEvent--->ACTION_DOWN E/MainActivity: dispatchTouchEvent--->ACTION_MOVE E/MainActivity: onTouchEvent--->ACTION_MOVE E/MainActivity: dispatchTouchEvent--->ACTION_UP E/MainActivity: onTouchEvent--->ACTION_UPSo:一切正常,只是不会在传递到下层

Ps:既然上层有拦截,那么下层就会有反拦截,这个方法为getParent().requestDisallowInterceptTouchEvent(boolean disallowIntercept);但是有的童鞋反应改该方法无效,其实这是因为调用时机不对,例如:

1.所有事件返回true,反拦截无效(因为根本没机会进入你下层的触摸事件)2.假设ViewGroupOne 的onInterceptTouchEvent这样写  @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                Log.e(TAG, "onInterceptTouchEvent--->ACTION_DOWN");                return false; //这里有机会进入下层            case MotionEvent.ACTION_MOVE:                Log.e(TAG, "onInterceptTouchEvent--->ACTION_MOVE");                return true;            case MotionEvent.ACTION_UP:                Log.e(TAG, "onInterceptTouchEvent--->ACTION_UP");                return false;        }        return super.onInterceptTouchEvent(ev);    }而TestView 的dispatchTouchEvent或者onTouchEvent 这样写   @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                Log.e(TAG, "dispatchTouchEvent--->ACTION_DOWN");                //getParent().requestDisallowInterceptTouchEvent(true);                //只有这里才好使,正常弹出土司(上层进入调用反拦截)                break;            case MotionEvent.ACTION_MOVE:                Log.e(TAG, "dispatchTouchEvent--->ACTION_MOVE");                //getParent().requestDisallowInterceptTouchEvent(true);                //上层已经拦截,进不来                break;            case MotionEvent.ACTION_UP:                Log.e(TAG, "dispatchTouchEvent--->ACTION_UP");                //getParent().requestDisallowInterceptTouchEvent(true);                break;        }        return super.dispatchTouchEvent(ev);    }

如果有错误请大家指出 反正我也不会改的 ~(≧▽≦)/~

开玩笑 (ฅ>ω<*ฅ)
原创粉丝点击