安卓事件传递机制个人理解版

来源:互联网 发布:小漠淘宝店网址 编辑:程序博客网 时间:2024/05/16 10:56

Android的触摸事件传递机制

Android中触摸事件传递过程中最重要的是dispatchTouchEvent()、onInterceptTouchEvent()和onTouchEvent()方法

dispatchTouchEvent是处理触摸事件分发,事件(多数情况)是从Activity的dispatchTouchEvent开始的。执行
super.dispatchTouchEvent(ev),事件向下分发。

onInterceptTouchEvent是ViewGroup提供的方法,默认返回false,返回true表示拦截。

onTouchEvent是View中提供的方法,ViewGroup也有这个方法,view中不提供onInterceptTouchEvent。view中默认返回true,表示消费了这个事件。

View里面只有两个函数
public boolean dispatchTouchEvent(MotionEvent event)
public boolean onTouchEvent(MotionEvent event)

而ViewGroup有3个函数
public boolean dispatchTouchEvent(MotionEvent event)
public boolean onTouchEvent(MotionEvent event)
public boolean onInterceptTouchEvent(MotionEvent ev)

在默认的情况下是从最外层ViewGroup接触到触摸事件然后触发
public boolean dispatchTouchEvent(MotionEvent event)
public boolean onTouchEvent(MotionEvent event)
这两个方法,然后往下传递到View

还是实例好说话先设置三个布局

布局一

public class View1 extends View{    public View1(Context context) {        super(context);    }    public View1(Context context, AttributeSet attrs) {        super(context, attrs);    }    public View1(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    //    不是父控件的view只有这两个方法    @Override    public boolean dispatchTouchEvent(MotionEvent event) {        Log.d("showevent","view_dispatchTouchEvent"+event.getAction());        return super.dispatchTouchEvent(event);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        Log.d("showevent","view_onTouchEvent"+event.getAction());        return super.onTouchEvent(event);    }}

布局二

public class View2 extends LinearLayout{    public View2(Context context) {        super(context);    }    public View2(Context context, AttributeSet attrs) {        super(context, attrs);    }    public View2(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    //    如果是父容器组件那么就比View多这一个的方法    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        Log.d("showevent","view2_onInterceptTouchEvent"+ev.getAction());        return false;//        return super.onInterceptTouchEvent(ev);    }//    处理触摸事件分发,事件(多数情况)是从Activity的dispatchTouchEvent开始的。执行//    super.dispatchTouchEvent(ev),事件向下分发。    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        Log.d("showevent","view2_dispatchTouchEvent"+ev.getAction());        return super.dispatchTouchEvent(ev);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        Log.d("showevent","view2_onTouchEvent"+event.getAction());         return super.onTouchEvent(event);    }}

布局三

public class View3 extends LinearLayout{    public View3(Context context) {        super(context);    }    public View3(Context context, AttributeSet attrs) {        super(context, attrs);    }    public View3(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    //    如果是父容器组件那么就比View多这一个的方法    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        Log.d("showevent", "view3_onInterceptTouchEvent" + ev.getAction());        return super.onInterceptTouchEvent(ev);    }    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        Log.d("showevent", "view3_dispatchTouchEvent" + ev.getAction());        return super.dispatchTouchEvent(ev);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        Log.d("showevent", "view3_onTouchEvent" + event.getAction());        return super.onTouchEvent(event);    }}

布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent">    <com.example.view_dispath.View3        android:background="#f42c2c"        android:layout_width="match_parent"        android:layout_height="match_parent">        <com.example.view_dispath.View2            android:background="#0ff8f8"            android:layout_width="300dp"            android:layout_height="300dp">            <com.example.view_dispath.View1                android:background="#7515ea"                android:layout_width="150dp"                android:layout_height="150dp" />        </com.example.view_dispath.View2>    </com.example.view_dispath.View3></RelativeLayout>

效果图

然后就是进行实例的研究

这是默认的情况下

可以看出传递的路径是这样的

view3_dis→view3_onInter→
viw2_dis→view2_onInter→
view_dis→
view_onTouch→view2_Touch→view3_Touch

事件传递从最外层的ViewGroup开始传递给里面的view
然后就是看看有没有外层的ViewGroup有没有进行事件的拦截 如果这个onInterceptTouchEvent不是true那么触摸事件就会往下传递。
然后事件消费实在onTouchEvent的里面进行消费
如果最里层的View没有把事件消费那么还是会从里层外传递。

然后把View2的dispatchTouchEvent设置为true其他都是初始化

事件传递到view2就停了,然后又传递到最外层的viewGroup处理但是最外层没有对事件做出事件的处理所以传给view2的dispatchTouchEvent进行处理。

然后把view2的onInterceptTouchEvent设置为true其他都是初始化

事件传递到view2的onInter就不传了所以在这里view2的OnInter拦截了 但是这里没有做出事件的消费所以给view2_onTouch消费 同样没有消费 所以返回给最外层的ViewGroup进行消费。

最后将view2_onTouch设置为true.其他都是初始化

事件像默认的一样进行传递但是在从里层返回触摸事件的时候view2_onTouch进行了拦截,所以没有返回给view3_onTouch。

0 0