View Touch源码解析

2017-09-09  本文已影响0人  dengzi_android

1、现象分析

    // 1、在自定义view中添加下面两个方法
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.e("dengzi", "dispatchTouchEvent." + getActionStr(event));
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.e("dengzi", "onTouchEvent." + getActionStr(event));
        return super.onTouchEvent(event);
    }

    // 2、在使用自定义view的地方添加两个listener
    customView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            Log.e("dengzi", "OnTouchListener." + getActionStr(event));
            return false;
        }
    });

    customView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.e("dengzi", "onClick");
        }
    });

    // 其中getActionStr()方法就是获取一下当前event的状态
    private String getActionStr(MotionEvent event){
        return event.getAction() == MotionEvent.ACTION_DOWN ? "Down"
                : event.getAction() == MotionEvent.ACTION_MOVE ? "Move"
                : event.getAction() == MotionEvent.ACTION_UP ? "Up" : "";
    }

现象一:就是上面的代码,直接运行看log日志

-> dispatchTouchEvent.Down -> OnTouchListener.Down -> onTouchEvent.Down
-> dispatchTouchEvent.Move -> OnTouchListener.Move -> onTouchEvent.Move
-> dispatchTouchEvent.Up -> OnTouchListener.Up -> onTouchEvent.Up
-> onClick

现象二:原始代码中OnTouchListener 中更改 : return true; ,运行看log日志

-> dispatchTouchEvent.Down -> OnTouchListener.Down
-> dispatchTouchEvent.Move -> OnTouchListener.Move
-> dispatchTouchEvent.Up -> OnTouchListener.Up

现象三:原始代码中onTouchEvent 中更改 : return true; ,运行看log日志

-> dispatchTouchEvent.Down -> OnTouchListener.Down -> onTouchEvent.Down
-> dispatchTouchEvent.Move -> OnTouchListener.Move -> onTouchEvent.Move
-> dispatchTouchEvent.Up -> OnTouchListener.Up -> onTouchEvent.Up

现象四:原始代码中dispatchTouchEvent中更改 : return true; ,运行看log日志

-> dispatchTouchEvent.Down 
-> dispatchTouchEvent.Move
-> dispatchTouchEvent.Up 

现象五:原始代码中删除OnTouchListener ,运行看log日志

-> dispatchTouchEvent.Down -> onTouchEvent.Down
-> dispatchTouchEvent.Move -> onTouchEvent.Move
-> dispatchTouchEvent.Up -> onTouchEvent.Up
-> onClick

现象六:原始代码中删除OnTouchListener ,并且onTouchEvent 中更改 : return true; 运行看log日志

-> dispatchTouchEvent.Down -> onTouchEvent.Down
-> dispatchTouchEvent.Move -> onTouchEvent.Move
-> dispatchTouchEvent.Up -> onTouchEvent.Up

现象七:原始代码中删除OnTouchListener ,并且onTouchEvent 中更改 : return false; 运行看log日志

-> dispatchTouchEvent.Down
-> onTouchEvent.Down

2、源码分析(android-25)
首先来看dispatchTouchEvent(event) 方法

    public boolean dispatchTouchEvent(MotionEvent event) {
        // ...
        // 初始化result 为 false
        boolean result = false;
        
        // ...

        final int actionMasked = event.getActionMasked();
        if (actionMasked == MotionEvent.ACTION_DOWN) {
            // 如果是Down,则停止一切滑动事件
            stopNestedScroll();
        }

        if (onFilterTouchEventForSecurity(event)) {
            // ...
            // ListenerInfo中存放着当前view的所有Listener事件
            ListenerInfo li = mListenerInfo;
            
            if (li != null // 当前view有设置Listener事件
                    && li.mOnTouchListener != null // 当前view有设置OnTouchListener事件
                    && (mViewFlags & ENABLED_MASK) == ENABLED // 当前view为Enabled状态
                    && li.mOnTouchListener.onTouch(this, event)) { // 当前view设置的OnTouchListener事件中返回true
                result = true; // result 置为 true
            }
            // 如果resut为false,则去调用onTouchEvent(),如果onTouchEvent()返回true,则将result 置为 true
            // 如果resut为true,则不调用onTouchEvent()。
            if (!result && onTouchEvent(event)) {
                result = true;
            }
        }
        // ...
        return result;
    }

接着来看onTouchEvent(event) 方法

    public boolean onTouchEvent(MotionEvent event) {
        // ...

        if (((viewFlags & CLICKABLE) == CLICKABLE ||
                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
            switch (action) {
                case MotionEvent.ACTION_UP:
                    // ...
                    // 设置点击事件
                    performClick();
                    // ...
                    break;
                case MotionEvent.ACTION_DOWN:
                    // 初化touch相当信息
                    break;
                case MotionEvent.ACTION_CANCEL:
                    // 将touch信息置为null
                    break;
                case MotionEvent.ACTION_MOVE:
                    // 移动相关
                    break;
            }
            return true;
        }
        return false;
    }

我们再来看performClick() 方法

    public boolean performClick() {
        final boolean result;
        final ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnClickListener != null) {
            // ...
            // 设置当前view的点击事件
            li.mOnClickListener.onClick(this);
         }
        return result;
    }

3、总结一下

20160601225357520.jpg
上一篇下一篇

猜你喜欢

热点阅读