android基础(事件分发)

来源:互联网 发布:淘宝代付可以用微信吗 编辑:程序博客网 时间:2024/06/08 13:47

view坐标体系: 


mLeft = getLeft();

mTop = getTop();

mRight = getRight();

mBottom = getBottom();


width = mRight - mLeft;

height = mBottom - mTop;


x = mLeft + translationX;

y = mTop + translationY;


View在平移过程中,mTop和mLeft表示的是原始左上角的位置信息,其值并不会发生改变,此时发生改变的是x、y、translationX和translationY


同一个事件序列是指从手指接触屏幕的那一刻起,到手指离开屏幕的那一刻结束。在这个过程中所产生的一系列事件,这个事件序列以down事件开始,中间含有数量不定的move事件,最终以up事件结束


通过MotionEvent对象我们可以得到点击事件发生的x和y坐标,为此,系统提供了两组方法:getX/getY和getRawX/getRawY,其中,getX/getY返回的是相对于当前View左上角的x和y坐标,而getRawX/getRawY返回的是相对于手机屏幕左上角的x和y坐标


TouchSlop:系统所能识别出的被认为是滑动的最小距离,ViewConfiguration.get(getContext()).getScaledTouchSlop(),我们在处理滑动时,可以利用这个值来做一些过滤,这样做可以有更好的用户体验


Scroller:


Scroller mScroller= new Scroller(mContext);

private void smoothScrollTo(int destX, int destY) {

    int scrollX = getScrollX();

    int delta = destX - scrollX;

    mScroller.startScroll(scrollX, 0, delta, 0, 1000);

    invalidate();

}

@Override

public void computeScroll() {

    if(mScroller.computeScrollOffset()) {

        scrollTo(mScroller.getCurrX(), mScroller.getCurrY());

        postInvalidate();

    }

}


activity事件分发:dispatchToucheventonTouchEvent

view事件分发:  dispatchTouchEventonTouchEvent


1. 05-22 00:15:28.905: I/MotionEventDispatch(22044): MainActivity-dispatchTouchEvent-ACTION_DOWN

2. 05-22 00:15:28.908: I/MotionEventDispatch(22044): CustomButton-dispatchTouchEvent-ACTION_DOWN

3. 05-22 00:15:28.908: I/MotionEventDispatch(22044): CustomButton-onTouch-ACTION_DOWN

4. 05-22 00:15:28.909: I/MotionEventDispatch(22044): CustomButton-onTouchEvent-ACTION_DOWN

5. 05-22 00:15:28.969: I/MotionEventDispatch(22044): MainActivity-dispatchTouchEvent-ACTION_UP

6. 05-22 00:15:28.969: I/MotionEventDispatch(22044): CustomButton-dispatchTouchEvent-ACTION_UP

7. 05-22 00:15:28.971: I/MotionEventDispatch(22044): CustomButton-onTouch-ACTION_UP

8. 05-22 00:15:28.971: I/MotionEventDispatch(22044): CustomButton-onTouchEvent-ACTION_UP

9. 05-22 00:15:28.975: I/MotionEventDispatch(22044): CustomButton--onClick

 

1. public boolean dispatchTouchEvent(MotionEvent event) {

2.     if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&

3.             mOnTouchListener.onTouch(this, event)) {

4.         return true;

5.     }

6.     return onTouchEvent(event);

7. }

 

mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && mOnTouchListener.onTouch(this, event)如果这三个条件都为真,那么dispatchTouchEvent就会返回true,表示事件已被处理否则的话就去执行onTouchEvent(event)onTouchEvent中会调用performClick方法,这里只要mOnClickListener不为空,就会触发onClick事件

 

1. public boolean onTouchEvent(MotionEvent event) {

1.   if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {

2.     ……

3.     performClick();

4.     ……

5.     return true;

6.   }

7.   return false;

8. }

 

如果View不消耗ACTION_DOWN事件,那么同一事件序列中的其他事件都不会再交给它来处理(不会再调用它的dispatchTouchEvent方法),并且事件将重新交由它的父元素去处理,即父元素的onTouch回调或者onTouchEvent处理

如果View消耗掉了ACTION_DOWN事件,但不消耗其他事件,此时父元素的onTouch或onTouchEvent并不会被调用,并且当前View可以持续收到后续的事件,最终这些消失的点击事件会传递给Activity的onTouchEvent处理

 ImageView在ACTION_DOWN执行完后,后面的一系列action都不会得到执行了因为ImageView和按钮不同,它是默认不可点击的,因此在onTouchEvent无法进入到if的内部,而是直接返回了false,也就导致后面其它的action都无法执行了

 

viewgroup事件分发:onInterceptTouchEventdispatchTouchEventonTouchEvent

 

1. 05-22 02:03:36.967: I/MotionEventDispatch(3045): MainActivity-dispatchTouchEvent-ACTION_DOWN  

2. 05-22 02:03:36.967: I/MotionEventDispatch(3045): CustomLayout-dispatchTouchEvent-ACTION_DOWN  

3. 05-22 02:03:36.967: I/MotionEventDispatch(3045): CustomLayout-onInterceptTouchEvent-ACTION_DOWN  

4. 05-22 02:03:36.967: I/MotionEventDispatch(3045): CustomButton-dispatchTouchEvent-ACTION_DOWN  

5. 05-22 02:03:36.967: I/MotionEventDispatch(3045): CustomButton-onTouch-ACTION_DOWN  

6. 05-22 02:03:36.967: I/MotionEventDispatch(3045): CustomButton-onTouchEvent-ACTION_DOWN  

7. 05-22 02:03:37.035: I/MotionEventDispatch(3045): MainActivity-dispatchTouchEvent-ACTION_UP  

8. 05-22 02:03:37.035: I/MotionEventDispatch(3045): CustomLayout-dispatchTouchEvent-ACTION_UP  

9. 05-22 02:03:37.036: I/MotionEventDispatch(3045): CustomLayout-onInterceptTouchEvent-ACTION_UP  

10. 05-22 02:03:37.036: I/MotionEventDispatch(3045): CustomButton-dispatchTouchEvent-ACTION_UP  

11. 05-22 02:03:37.036: I/MotionEventDispatch(3045): CustomButton-onTouch-ACTION_UP  

12. 05-22 02:03:37.036: I/MotionEventDispatch(3045): CustomButton-onTouchEvent-ACTION_UP  

13. 05-22 02:03:37.037: I/MotionEventDispatch(3045): CustomButton--onClick  

 

ViewGroup的dispatchTouchEvent方法中,判断是否拦截点击事件的逻辑:


1853            // Check for interception.1854            final boolean intercepted;1855            if (actionMasked == MotionEvent.ACTION_DOWN1856                    || mFirstTouchTarget != null) {1857                final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;1858                if (!disallowIntercept) {1859                    intercepted = onInterceptTouchEvent(ev);1860                    ev.setAction(action); // restore action in case it was changed1861                } else {1862                    intercepted = false;1863                }1864            } else {1865                // There are no touch targets and this action is not an initial down1866                // so this view group continues to intercept touches.1867                intercepted = true;1868            }

ViewGroup的onInterceptTouchEvent返回true后,即ViewGroup拦截事件后,onInterceptTouchEvent变不在被调用,因为mFristTouchTarget为空,且事件不是ACTION_DOWN,intercepted = true;,意味着父View拦截了ACTION_DOWN,子View变没有了翻身的机会

子View可以调用requestDisallowInterceptTouchEvent方法来设置是否允许父View拦截事件,但父View始终可以拦截ACTION_DOWN事件,因为事件序列开始时,父View的FLAG_DISALLOW_INTERCEPT标志位会被清空,意味着父View如果没拦截ACTION_DOWN,子View可以不允许父View拦截其他事件






1 0
原创粉丝点击