Android 事件分发

一、事件分发机制java

      用户点击产生一个MotionEvent,系统把这个事件分发给具体的view消费android

二、MotionEvent介绍json

     手势接触屏幕产生的事件 app

     MotionEvent对象操做有:ide

                                             一、MotionEvent.ACTION_DOWN   手势按下,是全部触发操做中最开始的动做布局

                                               二、MotionEvent.ACTION_UP 手势向上,是全部触发操做最后的动做spa

                                               三、MotionEvent.ACTION_MOVE 手势按下后没有收回code

                                             四、MotionEvent.ACTION_CANCEL  事件结束 理论上是ACTION_UP 后执行,但也有多是非人为因素致使的.xml

三、事件分发的本质对象

将MotinEvent传递到某个具体的view处理的过程

四、事件分发的对象及分发顺序

Activity ViewGroup View

Activity: 控制生命周期、处理事件

             统筹视图的现实和添加、经过其它回调方法与Window、View交互.

View:全部UI组件的基类

ViewGroup:一组view的组合,其自己也是view的子类,是android布局的全部父类.比view多了可包含子view和定义布局参数的功能.

 

五、事件分发的过程协助者

协助者:dispatchTouchEvent()、onInterceptTouchEvent()、onTouchEvent()

dispatchTouchEvent():用来进行事件的分发,当点击事件可以传递给当前view,该方法就会被调用.返回结果受到当前View的TouchEvent和下级view的dispatchTouchEvent方法影响,表示是否消费当前的事件

onTouchEvent:在dispatchTouchEvent方法内部调用,用来处理事件,返回结果表示是否消耗当前事件,若是不消耗,则在同一个事件序列中,当前view没法再接受到后续的事件队列。并且onTouchEvent返回值由clickable和longclickable共同决定

onInterceptTouchEvent():在dispatchTouchEvent()内部调用.用来表示是否拦截当前的事件.若是当前view拦截了某个事件,那么在同一个事件序列当中,此方法不会被调用,返回结果表示是否拦截当前事件。

 

六、代码说明演示

ViewGroup 表明 -》新建类DemoLayout 继承LinearLayout

public class DemoLayout extends LinearLayout {
    private static final String TAG = "DemoLayout";
    public DemoLayout(Context context) {
        super(context);
    }

    public DemoLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public DemoLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public DemoLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
//        父容器的分发事件
        Log.i(TAG, "----父容器的分发事件"+ev.getAction());
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:

                break;

            case MotionEvent.ACTION_MOVE:

                break;

            case MotionEvent.ACTION_UP:

                break;

            case MotionEvent.ACTION_CANCEL:

                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        //父容器的拦截事件
        Log.i(TAG, "----父容器的拦截事件"+ev.getAction());
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:

                break;

            case MotionEvent.ACTION_MOVE:

                break;

            case MotionEvent.ACTION_UP:

                break;

            case MotionEvent.ACTION_CANCEL:

                break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        //父容器的触摸事件
        Log.i(TAG, "----父容器的触摸事件"+ev.getAction());
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:

                break;

            case MotionEvent.ACTION_MOVE:

                break;

            case MotionEvent.ACTION_UP:

                break;

            case MotionEvent.ACTION_CANCEL:

                break;
        }
        return super.onTouchEvent(ev);
    }
}

 

View 表明-》 新建类View集成Button

public class View extends android.support.v7.widget.AppCompatButton {
    private static final String TAG = "View";
    public View(Context context) {
        super(context);
    }

    public View(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public View(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.i(TAG, "----子容器的分发事件"+ event.getAction());
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "----子容器的触摸事件"+event.getAction());
        return super.onTouchEvent(event);
    }

}

            操做准备:在layout布局中建立DemoLayout布局,包含View控件

<com.example.sunyuanfei.myapplication.DemoLayout
    android:layout_width="500dp"
    android:layout_height="500dp"
    android:clickable="true"
    android:background="#000000">

    <com.example.sunyuanfei.myapplication.View
        android:id="@+id/view_touch"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="事件分发"/>
</com.example.sunyuanfei.myapplication.DemoLayout>

初次运行看下运行流程:

没有拦截时

父容器把事件交给了子容器处理 dispatchTouchEvent进行事件分发 onInterceptTouchEvent没有拦截 子容器执行dispatchTouchEvent事件分发,再执行onTouchEvent事件

拦截后 代码和流程

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    //父容器的拦截事件
    Log.i(TAG, "----父容器的拦截事件"+ev.getAction());
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:

            break;

        case MotionEvent.ACTION_MOVE:

            break;

        case MotionEvent.ACTION_UP:

            break;

        case MotionEvent.ACTION_CANCEL:

            break;
    }
    return true;
}

DemoLayout  dispatchTouchEvent进行事件分发 onInterceptTouchEvent拦截  父容器执行onTouchEvent,(备注:父容器clickable默认值是false即表明onTouchEvent 返回false,后续操做系列Action_UP不会执行,以下图,因此在xml中要声明clickable="true").从上看出拦截事件onIntercepeTpuchEvent不会再执行,只会被消费一次

若子容器不消费onTouchEvent,则事件会传递给父容器,并且不会接受后续操做,父容器onInterceptTouchEvent也不会再执行.一样若子容器在xml声明clickable="false"也就表明着子容器的onTouchEvent返回false。(备注操做:事件系列操做指的是按下ACTION_DOWN、移动ACTION_MOVE、抬起ACTION_UP,所谓后续操做如图子容器的ACTION_UP就没有再执行了)

@Override
public boolean onTouchEvent(MotionEvent event) {
    Log.i(TAG, "----子容器的触摸事件"+event.getAction());
    return false;
}

若子容器的onTouchEvent返回false,onClick方法也是不可以执行的,由于回调方法onClick()是在onTouchEvent中执行的

 

总结

相关文章
相关标签/搜索