P137 第三章View的事件体系
3.1View的基础知识
1.View是Android中所有控件的基类
2.View的位置参数:top:左上角纵坐标;left:左上角横坐标;right:右下角横坐标;bottom:右下角纵坐标
3.MotionEvent和TouchSlop
(1)MotionEvent
ACTION_DOWN,
ACTION_MOVE,
ACTION_UP
getX/getY:返回相对于当前View的左上角的X和Y;
getRawX/getRawY:返回相对于手机屏幕左上角的x和Y的坐标
(2)TouchSlop:系统所能识别出的被认为是华东的最小距离;
获取方法:ViewConfiguration.get(getContext()).getScaledTouchSlop()
4.VelocityTracker,GestureDetector和Scroller
(1)VelocityTracker :速度追踪,用于追踪手指在滑动的过程中的速度P141
(2)GestureDector:用于辅助检测用户的单击,滑动,长按,双击等行为。P142
创建GestureDector对象 并实现OnGestureListener 或者OnDoubleTapListener接口 具体每个接口中的方法P143
实际开发中可以不使用GesureDector 直接使用view的onTouchEvent方法也可。监听双击行为可以使用GestureDector
(3)Scroller :弹性滑动事件,比scrollTo/scrollBy更具有过渡效果的滑动。使用代码P143
3.2View的滑动
1.使用scrollTo/scrollBy 它只能滑动View的内容,不能滑动View本身
2.使用动画
可以使用View动画也可以使用属性动画,为了兼容3.0以下版本需要采用动画开源库nineoldandroids(http://nineoldandroid.com/)
3.改变布局参数LayoutParams
MarginLayoutParams params=(MarginLayoutParams)mButton.getLayoutParams();
params.width+=100;params.leftmargin+=100; mButton.setLayoutparams(params)
3.3弹性滑动
1.使用scroller p152
Scroller本身并不能实现View的滑动,他需要配合View的computeScroll方法才能完成弹性滑动的效果,它不断地让View重绘,而每一次重绘距滑动起始时间会有一个时间间隔,通过这个时间间隔,Scroller就可以得出View的当前位置,知道了当前位置就可以通过scrollTo方法来完成小幅度滑动就组成了弹性滑动。
2.使用动画
3,使用延时策略
3.4View的事件分发机制
点击事件传递规则,对一个根ViewGroup来说,点击事件产生后,首先传递给它,这时它的dispatchTouchEvent就会被调用,如果这个ViewGroup的onInterceptTouchEvent返回true就表示他要拦截当前事件,接着事件就会交给ViewGroup处理,即他的onTouchEvent方法就不会被调用;如果这个ViewGroup的onInterceptTouchEvent方法返回false,就表示他不拦截当前事件,就会传递给他的子元素,接着子元素的dispatchTouchEvent方法就会被调用,如此反复。
p157
3.5 滑动冲突
1.外部滑动方向和内部滑动方向不一致,
解决办法:1.外部拦截法: 指点击事件都先经过父容器拦截处理 需要重写父容器的onInterceptTouchEvent方法
伪代码P174
描述:在onInterceptTouchEvent方法中,首先是ACTION_DOWN这事件,父容器必须返回false,不拦截这个事件,因为一旦拦截,那么后续的ACTION_MOVE和ACTION_UP都必须有父容器处理;其次是ACTION_MOVE,根据需要拦截,拦截返回true,不拦截返回false;最后是ACTION_UP,一般返回false,如果返回true,导致子元素无法接收ACTION_UP事件,这时候的子元素中的onClick时间就无法处触发,但是父容器比较特殊,一旦他开始拦截任何一个事件,那么后续的事件都会交给他来处理,ACTION_UP方法一定可以传给父容器,即使他返回false。
2.内部拦截法:是指父容器不拦截任何事件,所有的事件都传递给子元素,如果子元素需要就消耗掉,否则就交给父容器处理。
需要配合requestDisallowInterceptTouchEvent方法才能正常工作 伪代码:P174
描述。重写子元素的dispatchTouchEvent方法。除了子元素需要做处理外。父元素也要默认拦截除了ACTION_DOWN以外的其他事件,这样当子元素调用parent.requestDisallowInterceptTouchEvent(false)方法时,父元素才能继续拦截所需要的事件。 父元素不能拦截ACTION_DOWN(在ACTION_DOWN,中parent.requestDisallowInterceptTouchEvent(true)),因为它不受FLAG_DIASLLOW_INTERCEPT这个标记为控制,一旦拦截将无法传递到子元素中
父元素的onInterceptTouchEvent 在ACTION_DOWN中返回false 其他返回true即可
2.内部滑动方向和外部滑动方向一致时(都是上下滑动
父容器StickyLayout (是一个LinearLayout)子容器ListView
重写父容器的onInterceptTouchEvent方法 分析其中的ACTION_MOVE方法:当事件落在Header上面时父容器不会拦截事件;接着如果竖直距离小于水平距离差,那么父容器也不会拦截事件;然后,当Header是展开状态并且向上滑动时父容器拦截事件。另外一种情况,当ListView滑动到了顶部并且向下滑动时,父容器也会拦截事件。