美文网首页
View Touch源码解析

View Touch源码解析

作者: dengzi_android | 来源:发表于2017-09-09 17:32 被阅读0次

    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

    相关文章

      网友评论

          本文标题:View Touch源码解析

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