文章

[摘]View的基础知识

文章目录

前言

这边文章总结得不错,对View的总结很到位。

因此摘抄于此,方便自己学习。

View的基础知识

了解View,可以有效的使用View

mTop mLeft mRight mBottom

View的位置主要通过它的四个顶点来决定,对应View的四个属性。

  1. mTop 左上角纵坐标
  2. mLeft 左上角横坐标
  3. mRight 右下角横坐标
  4. 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

手指接触屏幕后产生的一系列事件中,典型的事件如下:

  1. ACTION_DOWN——手指刚接触屏幕。
  2. ACTION_MOVE——在屏幕上移动。
  3. ACTION_DOWN——从屏幕上松开。

这些事件对应MotionEvent类中的几个静态常量。

public static final int ACTION_DOWN = 0;
public static final int ACTION_UP   = 1;
public static final int ACTION_MOVE = 2;

正常情况下的一些列点击事件:

  1. 点击屏幕后立即松开,ACTION_DOWN->ACTION_UP
  2. 点击屏幕滑动后再松开,ACTION_DOWN->ACTION_MOVE->......->ACTION_MOVE->ACTION_UP
  3. 可以通过MotionEvent对象调用getX()、getY()、getRawX()、getRawY()获取触碰点的位置参数。
  4. getX()、getY() 相对于当前View左上角的x、y值。
  5. 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()中追踪当前单击事件的速度。

  1. 首先获得一个VelocityTracker对象,再将当前时间加入进去。
VelocityTracker velocityTracker = VelocityTracker.obtain();
velocityTracker.addMovement(event);
  1. 计算自定义时间内的速度,再调用get获得定义时间内划过的像素点。
velocityTracker.computeCurrentVelocity(1000);
int xVelocity = (int) velocityTracker.getXVelocity();
int yVelocity = (int) velocityTracker.getYVelocity();
  1. 计算真正的速度。
int xV = xVelocity / 1;//这里的1是上面计算时间时定义的时间间隔1000ms
int yV = yVelocity / 1;
  1. 回收资源。
velocityTracker.clear();
velocityTracker.recycle();

PS:

  1. 获取速度之前必须要调用computeCurrentVelocity()计算速度。
  2. 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。

摘抄来源

  1. Android View相关(一)View的参数与滑动实现
发表评论