美文网首页
View的事件分发

View的事件分发

作者: Sky_Blue | 来源:发表于2018-04-17 16:14 被阅读30次
一、自定义View的套路
1. 自定义属性
2. onMeasure用于测量控件的大小
3. onDraw用于绘制内容
4. onTouchEvent用于用户交互
二、自定义ViewGroup的套路
1. 自定义属性
2. onMeasure for循环测量子View的宽高,最后计算自己的宽高 
3. onLayout 用于摆放子View,前提是View不是Gone的情况
4. onDraw用于绘制自己,默认是不调用,如果要绘制就复写dispatchDraw
5. onTouchEvent用于用户交互
三、View的事件分发,两个重要方法
1. dispatchTouchEvent(MotionEvent event) 负责事件分发,事件是从这个方法开始分发的。
2. onTouchEvent(MotionEvent event) 触摸事件。
四、dispatchTouchEvent(MotionEvent event)源码分析
public boolean dispatchTouchEvent(MotionEvent event) {
   
    boolean result = false;

    if (onFilterTouchEventForSecurity(event)) {
        // ListenerInfo 封装事件监听的对象,里面封装了一系统列的事件监听回调对象
        // 只要是设置了监听事件,这个对象就不为空。
        ListenerInfo li = mListenerInfo;
        
      // 1. 如果给View设置了OnTouchListener,
      // 那么就会先调用 li.mOnTouchListener.onTouch(this, event)这个方法
      // 如果onTouch返回 false , result就是false
      // 如果onTouch返回 true,    result就是true
        if (li != null && li.mOnTouchListener != null
                && (mViewFlags & ENABLED_MASK) == ENABLED // 控件是enabled
                && li.mOnTouchListener.onTouch(this, event)) {
            result = true;
        }
        // 如果没有设置OnTouchListener,或者onTouch返回false用户没有消费事件
        // 那么就会走View的onTouchEvent方法
        if (!result && onTouchEvent(event)) {
            result = true;
        }
    }
    return result;
}
  1. 如果View没有设置OnTouchListener,或者设置OnTouchListener且onTouch返回false,用户没有消费事件,那么就会走View的 onTouchEvent(event)方法
五、onTouchEvent(MotionEvent event)源码分析
public boolean onTouchEvent(MotionEvent event) {
    final float x = event.getX();
    final float y = event.getY();
    final int viewFlags = mViewFlags;
    final int action = event.getAction();

    if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
        switch (action) {
            // 在onTouchEvent 事件抬起的方法,里面有对点击事件的处理
            case MotionEvent.ACTION_UP:
              
                    if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
                        // This is a tap, so remove the longpress check
                        removeLongPressCallback();

                        // Only perform take click actions if we were in the pressed state
                        if (!focusTaken) {
                            // Use a Runnable and post this rather than calling
                            // performClick directly. This lets other visual state
                            // of the view update before click actions start.
                            if (mPerformClick == null) {
                                mPerformClick = new PerformClick();
                            }
                            if (!post(mPerformClick)) {
                                // 执行点击事件
                                performClick();
                            }
                        }
                    }

                break;
            // 在onTouchEvent 事件抬起的方法,里面有对LongClick点击事件的处理
            case MotionEvent.ACTION_DOWN:
                checkForLongClick(0, x, y);
                break;

        }

        return true;
    }

    return false;
}
// 执行点击事件
public boolean performClick() {
    final boolean result;
    final ListenerInfo li = mListenerInfo;
    if (li != null && li.mOnClickListener != null) {
        playSoundEffect(SoundEffectConstants.CLICK);
        // 执行点击事件
        li.mOnClickListener.onClick(this);
        result = true;
    } else {
        result = false;
    }
    return result;
}
  1. 点击和长按事件都在View的onTouchEvent里面
  2. 点击事件的处理是在onTouchEvent ACTION_UP里面
  3. 长按事件的处理是在onTouchEvent ACTION_DOWN里面
  4. OnTouchListener的onTouch方法返回false,事件执行顺序:OnTouchListener-->onTouchEvent-->onClickListener

相关文章

网友评论

      本文标题:View的事件分发

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