Android 事件分发机制,事件的传递流程

事件分发

  • 事件
    用户通过屏幕与手机交互时,每次点击、长按、移动等都是一个事件。
  • 事件分发
    某一个事件从屏幕传递到各个View,由View来消费事件或者忽略这一事件的过程。

事件分发的对象

  • 系统把事件封装为MotionEvent对象,事件分发的过程就是MotionEvent分发的过程。
  • 事件类型:
    按下(ACTION_DOWN)
    移动(ACTION_MOVE)
    抬起(ACTION_UP)
    取消(ACTION_CANCEL)

事件序列

  • 从手指按下屏幕开始,到手指离开屏幕所产生的一系列事件。
  • 同一事件序列,如果子View(ViewGroup)没有处理该事件(没有消费事件),那么后续事件就不会再传递到子View中。如果没有任何子View处理,就会交给Activity的onTouchEvent处理。

传递层级

  • Activity→Window→DecorView→ViewGroup→View
    如果没有被消费,则一层层的向上传递到Activity(通过每层的onTouchEvent方法)

Activity事件分发

在这里插入图片描述

    //1.开始
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        	//空方法,可以重写这个方法来监听事件的开始
            onUserInteraction();
        }
        //会跳转到第3点
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);
    }

    //2.Window是一个抽象类,只有一个子类PhoneWindow(窗口),PhoneWindow内部有个DecorView
    public class PhoneWindow extends Window implements MenuBuilder.Callback {
		...
        private DecorView mDecor;
		//3.
        public boolean superDispatchTouchEvent(MotionEvent event) {
            return mDecor.superDispatchTouchEvent(event);
        }
    }

    //4.DecorView继承自FrameLayout,它是Activity下的最顶层View,我们setContentView(R.layout.activity_test);的时候就是设置到这个DecorView中的
    public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {
		...
		//5.在DecorView中superDispatchTouchEvent方法,进入到ViewGroup中的dispatchTouchEvent
    	public boolean superDispatchTouchEvent(MotionEvent event) {
        	return super.dispatchTouchEvent(event);
    	}
    }

 	//6.这个是ViewGroup中的
    public boolean dispatchTouchEvent(MotionEvent ev) {
    	...
    }

ViewGroup事件分发

在这里插入图片描述
ViewGroup:dispatchTouchEvent

  • 0.判断安全策略,判断一个ViewGroup不处于视图的顶部
  • 1.去判断是否需要拦截事件(可以重写onInterceptTouchEvent,返回true来拦截ViewGroup中的事件)
  • 2.在当前ViewGroup中找到用户真正点击的View
  • 3.分发事件到该View上

ViewGroup中事件透传

  • 判断是否是滑动事件,如果是,则额外处理滑动事件,然后继续向下分发事件
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        //判断是否滑动事件
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                down_y = (int) ev.getRawY();
                break;
            case MotionEvent.ACTION_UP:
                if (Math.abs(ev.getRawY() - down_y) > 10){
                    if (onDispatchTouchListener != null) {
                        onDispatchTouchListener.dispatchTouchEvent();
                    }
                }
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

ViewGroup中事件拦截

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
       //onInterceptTouchEvent中返回true则会拦截事件,停止向下传递
        return true;
    }

View事件分发

在这里插入图片描述

//1.dispatchTouchEvent
//2.onTouchEvent
    public boolean dispatchTouchEvent(MotionEvent event) {
        ...
        //判断安全策略
        if (onFilterTouchEventForSecurity(event)) {
            //鼠标滚动条拖动
            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
                result = true;
            }
            //已注册TouchListener,监听onTouch()返回值
            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnTouchListener != null
                    && (mViewFlags & ENABLED_MASK) == ENABLED
                    && li.mOnTouchListener.onTouch(this, event)) {
                result = true;
            }
            //最终传递给onTouchEvent
            if (!result && onTouchEvent(event)) {
                result = true;
            }
        }
        ...
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值