目录
前言
这边文章总结得不错,对View的总结很到位。
因此摘抄于此,方便自己学习。
View的基础知识
了解View,可以有效的使用View
mTop mLeft mRight mBottom
View的位置主要通过它的四个顶点来决定,对应View的四个属性。
- mTop 左上角纵坐标
- mLeft 左上角横坐标
- mRight 右下角横坐标
- mBottom 右下角纵坐标
getTanslationX() getTranslationY()
Android3.0之后提供的两个方法,getTranslationX()和getTranslationY(),它们不同于上面的四个参数,这两个参数会由于 View的平移而变化,表示View左上角坐标相对于left、top(原始左上角坐标)的偏移量
getX() getY()
Android3.0之后提供了getX()和getY()两个方法。
@ViewDebug.ExportedProperty(category = "drawing") public float getX() { return mLeft + getTranslationX(); }
代码是将mLeft加上translationX得到x的,可以看出来,x和y代表的就是当前View左上角相对于父布局的偏移量。
MotionEvent
手指接触屏幕后产生的一系列事件中,典型的事件如下:
- ACTION_DOWN——手指刚接触屏幕。
- ACTION_MOVE——在屏幕上移动。
- ACTION_DOWN——从屏幕上松开。
这些事件对应MotionEvent类中的几个静态常量。
public static final int ACTION_DOWN = 0; public static final int ACTION_UP = 1; public static final int ACTION_MOVE = 2;
正常情况下的一些列点击事件:
- 点击屏幕后立即松开,ACTION_DOWN->ACTION_UP
- 点击屏幕滑动后再松开,ACTION_DOWN->ACTION_MOVE->......->ACTION_MOVE->ACTION_UP
- 可以通过MotionEvent对象调用getX()、getY()、getRawX()、getRawY()获取触碰点的位置参数。
- getX()、getY() 相对于当前View左上角的x、y值。
- getRawX()、getRawY() 相对于手机屏幕左上角的x、y值。
TouchSlop
TouchSlop是系统能识别的最小滑动距离,如果小于这个值,则不认为是滑动。这是一个常量和设备有关,可以通过以下方式获得。
ViewConfiguration.get(getContext()).getScaledTouchSlop(); public int getScaledTouchSlop() { return mTouchSlop; }
这个mTouchSlop在ViewConfiguration的无参构造器中用一个常量赋了初始值为8。
private static final int TOUCH_SLOP = 8; @Deprecated public ViewConfiguration() { //... mTouchSlop = TOUCH_SLOP; //... }
有参构造器中初始化为资源文件的一个值,这个值也是8。
<!-- Base "touch slop" value used by ViewConfiguration as a movement threshold where scrolling should begin. --> <dimen name="config_viewConfigurationTouchSlop">8dp</dimen> private ViewConfiguration(Context context) { //... mTouchSlop = res.getDimensionPixelSize(com.android.internal.R.dimen.config_viewConfigurationTouchSlop); //... }
在处理滑动的时候可以使用这个值来做一些过滤,过滤掉滑动距离小于这个值,会有更好的用户体验。
Velocity Tracker
用来获取手指滑动过程中的速度,包括水平速度和垂直速度。
在onTouchEvent()中追踪当前单击事件的速度。
- 首先获得一个VelocityTracker对象,再将当前时间加入进去。
VelocityTracker velocityTracker = VelocityTracker.obtain(); velocityTracker.addMovement(event);
- 计算自定义时间内的速度,再调用get获得定义时间内划过的像素点。
velocityTracker.computeCurrentVelocity(1000); int xVelocity = (int) velocityTracker.getXVelocity(); int yVelocity = (int) velocityTracker.getYVelocity();
- 计算真正的速度。
int xV = xVelocity / 1;//这里的1是上面计算时间时定义的时间间隔1000ms int yV = yVelocity / 1;
- 回收资源。
velocityTracker.clear(); velocityTracker.recycle();
PS:
- 获取速度之前必须要调用computeCurrentVelocity()计算速度。
- getXVelocity()\getYVelocity()获取到的是计算单位时间内滑过的像素值,并不是速度。
GestureDetector
GestureDetector用于检测用户的单击、滑动、长按、双击等行为。
GestureDetector内部有两个监听接口,OnGestureListener和OnDoubleTapListener,里面的方法可以根据需求去实现。
public interface OnGestureListener { boolean onDown(MotionEvent e);//手指轻轻触摸屏幕的一瞬间,一个ACTION_DOWN触发 void onShowPress(MotionEvent e);//手指轻触屏幕,没有松开或挪动 boolean onSingleTapUp(MotionEvent e);//轻触后松开,单击行为,伴随一个ACTION_UP触发 boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);//拖动行为,由一个ACTION_DOWN和一系列ACTION_MOVE触发 void onLongPress(MotionEvent e);//长按 boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);//按下快速滑动后松开,一个ACTION_DOWN、多个ACTION_MOVE和一个ACTION_UP触发 }
public interface OnDoubleTapListener { boolean onSingleTapConfirmed(MotionEvent e);//严格的单击行为,不能是双击中的其中一次单击,onSingleTapUp可以是双击中的其中一次。 boolean onDoubleTap(MotionEvent e);//双击,两次单击,不可能和onSingleTapConfirmed共存 boolean onDoubleTapEvent(MotionEvent e);//双击行为,双击期间ACTION_DOWN ACTION_MOVE ACTION_UP都会触发此回调。 }
创建一个GestureDetector,根据需要实现接口并传入GestureDetector。
gestureDetector = new GestureDetector(context, gestureListener); gestureDetector.setOnDoubleTapListener(doubleTapListener); gestureDetector.setIsLongpressEnabled(false);//解决长按屏幕后无法拖动的现象
接管View的onTouchEvent(),GestureDetector的onTouchEvent()中会根据event来回调上面说的两个接口方法。
@Override public boolean onTouchEvent(MotionEvent event) { boolean consume = gestureDetector.onTouchEvent(event); return consume; }
PS:
并不是必须要用GestureDetector来实现所需的监听,完全也可以直接在View的onTouchEvent()中做判断并实现需求。所以,如果只需要监听简单的单击事件就可以直接使用View的onTouchEvent(),如果需要监听复杂一点的一系列事件,就可以使用GestureDetector。
摘抄来源