美文网首页
Android事件分发

Android事件分发

作者: 海内灬存知己 | 来源:发表于2020-01-07 20:48 被阅读0次

    努力第一弹,把事件分发弄明白,本文主要看考资料有

    Android事件分发机制详解:史上最全面、最易懂
    android中的事件传递和处理机制

    一问:为什么要研究事件分发,事件分发对我们有什么帮助?

    原因有二:

    第一点:面试,做开发,难免会换工作,当面试官问你的时候,你如果支支吾吾答不上来,想必对你的印象会大打折扣

    第二点:开发中的应用,例如一些滑动嵌套,掌握了事件分发,分分钟解决问题

    既然我们已经知道了事件分发是非常有意义的知识点,那么下一步就是学习它

    二问:事件分发的对象是谁?

    答:点击事件(Touch事件

    定义:

    当用户触摸屏幕时(View或ViewGroup派生的控件),将产生点击事件(Touch事件)

    Touch事件的相关细节(发生触摸的位置、时间等)被封装成MotionEvent对象

    事件类型(4种)

    事件类型具体动作

    MotionEvent.ACTION_DOWN按下View(所有事件的开始)

    MotionEvent.ACTION_UP抬起View(与DOWN对应)

    MotionEvent.ACTION_MOVE滑动View

    MotionEvent.ACTION_CANCEL结束事件(非人为原因)

    三问:事件分发的本质

    答:将点击事件(MotionEvent)传递到某个具体的View& 处理的整个过程

    即 事件传递的过程 = 分发过程。

    四问:事件在哪些对象之间进行传递?

    答:Activity、ViewGroup、View

    五问:事件分发过程由哪些方法协作完成?

    答:dispatchTouchEvent() 、onInterceptTouchEvent()和onTouchEvent()

    经过以上五问以后,我们大概应该对事件分发有个大体的了解了,下面我们就去看一下,事件分发是如何分发的

    一:Activity的事件分发机制

    当一个点击事件发生时,事件最先传到Activity的dispatchTouchEvent()进行事件分发

    源码分析:

    
    public boolean dispatchTouchEvent(MotionEvent ev) {
    
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
    
    //这个方法是按下的时候执行,所以一定会执行,一个空方法而已
    
    当此activity在栈顶时,触屏点击按home,back,menu键等都会触发此方法,可以忽略
    
    onUserInteraction();
    
        }
    
    //这句话实现了从Activity向ViewGroup传递了,(分析一)
    
    if (getWindow().superDispatchTouchEvent(ev)) {
    
    return true;
    
        }
    
    return onTouchEvent(ev);
    
    }
    
    

    分析一:

    为什么说这句话实现了从Activity向ViewGroup传递了呢?

    因为window的实现类是PhoneWindow,而PhoneWindow的superDispatchTouchEvent方法返回 mDecor.superDispatchTouchEvent(event);

    b. DecorView继承自FrameLayout,是所有界面的父类

    c. FrameLayout是ViewGroup的子类,故DecorView的间接父类 = ViewGroup

    image

    那么,ViewGroup的dispatchTouchEvent()什么时候返回true/false?请继续往下看ViewGroup事件的分发机制

    二:ViewGroup事件的分发机制

    从上面Activity事件分发机制可知,ViewGroup事件分发机制从dispatchTouchEvent()开始

    源码分析:

    
    //仅贴出关键代码,省略无用部分
    
    @Override
    
    public boolean dispatchTouchEvent(MotionEvent ev) {
    
    // 分析一
    
    if (!canceled && !**intercepted**) {
    
    // 通过for循环,遍历了当前ViewGroup下的所有子View
    
    for (int i = childrenCount -1; i >=0; i--) {
    
    //分析二
    
    if (**dispatchTransformedTouchEvent**(ev, false, child, idBitsToAssign)) {
    
    ......
    
    break;
    
    }}}}
    
    

    分析一:

    intercepted 是onInterceptTouchEvent()的返回值

    a. 若在onInterceptTouchEvent()中返回false(即不拦截事件),就会让第二个值为true,从而进入到条件判断的内部

    b. 若在onInterceptTouchEvent()中返回true(即拦截事件),就会让第二个值为false,从而跳出了这个条件判断

    分析二:dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)方法内部调用了child.dispatchTouchEvent(event);

    从而实现了事件从ViewGroup到View的传递

    image

    三:View事件的分发机制

    源码分析:

    
    public boolean dispatchTouchEvent(MotionEvent event) {
    
    分析一
    
    if (li !=null && li.mOnTouchListener !=null
    
            && (mViewFlags &ENABLED_MASK) ==ENABLED
    
            && li.mOnTouchListener.onTouch(this, event)) {
    
    result =true;
    
    }
    
    分析二
    
    if (!result && onTouchEvent(event)) {
    
    result =true;
    
    }
    
    return result;
    
    }
    
    

    分析一:

    满足这三个条件就返回true,否则向下进行,其中最后一个条件是由mOnTouchListener提供者返回值,例如:

    
    button.setOnTouchListener(new OnTouchListener(){
    
    @Override
    
    public boolean onTouch (View v , Motion Eventevent){
    
    return false;
    
    }});
    
    

    分析二:

    调用onTouchEvent(event),结果为true则返回true,onTouchEvent方法中会执行OnClick()方法

    image

    相关文章

      网友评论

          本文标题:Android事件分发

          本文链接:https://www.haomeiwen.com/subject/dxmdactx.html