View的事件体系
1.1 View简述
- View是Android中所有控件的基类。View是一种界面层的控件的一种抽象,代表一个控件。
- ViewGroup:控件组。ViewGroup内部包含多个控件(View)。ViewGroup也继承View,意味着View本身就可以是单个控件也可以是多个控件组成的一组控件。
1.1.1 View的位置参数
View的位置由四个顶点确定,对应View的四个属性:top(左上纵坐标)、left(左上横坐标)、right(右下横坐标)、bottom(右下纵坐标)。
View的宽高和坐标关系:
width = right - left
height = bottom - top
位置参数的获取方法:
Left=getLeft()
Right=getRight()
Top=getTop()
Bottom=getBottom()
View的其他参数:
x:View的左上角横坐标
y:View的左上角纵坐标
translationX:View的左上角横坐标相对于父容器的偏移量。(默认0)
translationY:View的左上角纵坐标相对于父容器的偏移量。(默认0)
x=left+translationX
y=top+translationY
注意:top和left表示的是原始左上角的位置信息,不会改变;x、y、translationX、translationY这四个参数会发生改变。
1.1.2 MotionEvent和TouchSlop
MotionEvent:
- ACTION_DOWN:手指刚接触屏幕。
- ACTION_MOVE:手指在屏幕上移动。
- ACTION_UP:手指从屏幕上松开的一瞬间。
- 通过MotionEvent对象可以获取点击事件发生的x和y坐标。getX/getY返回相对于当前View左上角的x和y坐标;getRawX/getRawY返回相对于手机屏幕左上角的x和y坐标。
TouchSlop:
- 系统所能识别出的被认为是滑动的最小距离。TouchSlop是一个和设备相关的常量。通过
ViewConfiguration.get(getContext()).getScaledTouchSlop()
方法获取。
1.1.3 VelocityTracker、GestureDetector、Scroller
VelocityTracker:
速度追踪。
/** * 在View的onTouchEvent方法中追踪当前点击事件的速度 */ VelocityTracker velocityTracker = VelocityTracker.obtain(); velocityTracker.addMovement(event); /** * 获取当前速度 * 要在获取速度前调用computeCurrentVelocity()计算速度。单位ms。 * 速度是指一段时间内手指所划过的像素数。带方向,可以为负值。 * 速度 = (终点位置 - 起点位置)/时间段 */ velocityTracker.computeCurrentVelocity(1000); int xVelocity=(int)velocityTracker.getXvelocity(); int yVelocity=(int)velocityTracker.getYvelocity(); /** * 不需要时,需要重置并回收内存 */ velocityTracker.clear() velocityTracker.recycle()
GestureDetector:
手势检测。
/** * 创建GestureDetector对象,并实现OnGestureListener接口 */ GestureDetector mGestureDetector = new GestureDetector(this); //解决长按屏幕后无法无法拖动现象 mGestureDetector.setIsLongpressEnabled(false); /** * 在View的onTouchEvent方法中实现 */ boolean consume = mGestureDetector.onTouchEvent(event); return consume;
完成上述步骤后,可选择性地实现OnGestureListener和OnDoubleTapListener中的方法:
方法名 描述 所属接口 onDown 手指轻轻触摸屏幕的一瞬间,由1个ACTION_DOWN触发 OnGestureListener onShowPress 手指轻轻触摸屏幕,尚未松开或拖动,由1个ACTION_DOWN触发。和onDown()的区别:它强调的是没有松开或者拖动的状态。 OnGestureListener onSingleTapUp 手指(轻触摸屏幕后)松开,伴随着1个 ACTION_UP触发,是单击行为。 OnGestureListener onScroll 手指按下屏幕并拖动,由1个ACTION_DOWN,多个ACTION_MOVE触发,是拖动行为。 OnGestureListener onLongPress 用户长久地按着屏幕不放,即长按。 OnGestureListener onFling 用户按下触摸屏、快速滑动后松开,由1个ACTION_DOWN、多个ACTION_MOVE和1个ACTION_UP触发,是快速滑动行为。 OnGestureListener onDoubleTap 双击,由2次连续的单击组成。不可能和onSingleTapConirned共存。 OnDoubleTapListener onSingleTapConfirmed 严格的单击行为。和onSingleTapUp的区别:如果触发了onSingleTapConfirmed,那么后面不可能再紧跟着另一个单击行为,即这只可能是单击,而不可能是双击中的一次单击。 OnDoubleTapListener onDoubleTapEvent 双击行为,在双击的期间,ACTION DOWN、ACTION_ MOVE和ACTION_ UP都会触发此回调。 OnDoubleTapListener 常用:onSingleTapUp、onFling、onScroll、onLongPress、onDoubleTap。
注意:实际开发中,可以不使用GestureDetector,可以完全在View的ontouchEvent方法中实现所需监听。
Scroller:
弹性滑动。
View的scollTo/scrollBy方法进行滑动时,过程是瞬间完成的,没有过渡效果。Scroller可以实现有过渡效果的滑动,Scroller本身无法让View弹性滑动,需要和View的computeScroll方法配合实现。
典型代码:
Scroller mScroller = new Scroller(mContext); //缓慢滚动到指定位置 private void smoothScrollTo(int destX,int destY){ int scrollX = getScrollX(); int delta = destX - scrollX; // 1000ms 内滑向 destX,效果就是慢慢滑动 mScroller.startScroll(scrollX,0,delta,1000); invalidate(); } @Override public void computeScroll(){ if(mScroller