View基础知识

521 阅读4分钟

View的位置参数

View的位置主要由它的四个顶点来决定,分别对应于View的四个属性:top、left、right、bottom,其中top是左上角纵坐标,left是左上角横坐标,right是右下角横坐标,bottom是右下角纵坐标。需要注意的是,这些坐标都是相对于View的父容器来说的,因此它是一种相对坐标。我们很容易得出View的宽高和坐标的关系:

width = right - left;
height = bottom - top;

那么如何得到View的这四个参数呢?也很简单,在View的源码中它们对应于mLeft、mRight、mTop和mBottom这四个成员变量,获取方式如下所示。· Left = getLeft();· Right = getRight();· Top = getTop;· Bottom = getBottom()。从Android3.0开始,View增加了额外的几个参数:x、y、translationX和translationY,其中x和y是View左上角的坐标,而translationX和translationY是View左上角相对于父容器的偏移量。这几个参数也是相对于父容器的坐标,并且translationX和translationY的默认值是0,和View的四个基本的位置参数一样,View也为它们提供了get/set方法,这几个参数的换算关系如下所示。

x = left + translationX;
y = top + translationY;

为什么要这样换算View左上角的坐标呢?因为View在平移的过程中,top和left表示的是原始左上角的位置信息,其值并不会发生改变,此时发生改变的是x、y、translationX和translationY这四个参数。因此只要知道了View相对于父容器的偏移量(translationX,translationY),就可以算出移动后View的左上角坐标。

TouchSlop是系统所能识别出的被认为是滑动的最小距离,换句话说,当手指在屏幕上滑动时,如果两次滑动之间的距离小于这个常量,那么系统就不认为你是在进行滑动操作。这是一个常量,和设备有关,在不同设备上这个值可能是不同的,通过如下方式即可获取这个常量:ViewConfiguration.get(getContext()).getScaledTouchSlop()。这个常量有什么意义呢?当我们在处理滑动时,可以利用这个常量来做一些过滤,比如当两次滑动事件的滑动距离小于这个值,我们就可以认为未达到滑动距离的临界值,因此就可以认为它们不是滑动,这样做可以有更好的用户体验。

VeIocityTracker 速度追踪,用于追踪手指在滑动过程中的速度,包括水平和竖直方向的速度。它的使用过程很简单,首先,在View的onTouchEvent方法中追踪当前单击事件的速度:

VelocityTracker mTracker = VelocityTracker.obtain();
mTracker.addMovement(event);

当我们先知道当前的滑动速度时,这个时候可以采用如下方式来获得当前的速度:

mTracker.computeCurrentVelocity(1000);
float xVelocity = mTracker.getXVelocity();

在这一步中有两点需要注意,第一点,获取速度之前必须先计算速度,即getXVelocity和getYVelocity这两个方法的前面必须要调用computeCurrentVelocity方法;第二点,这里的速度是指一段时间内手指所滑过的像素数,比如将时间间隔设为1000ms时,在1s内,手指在水平方向从左向右滑过100像素,那么水平速度就是100。注意速度可以为负数,当手指从右往左滑动时,水平方向速度即为负值。

GestureDetector手势检测,用于辅助检测用户的单击、滑动、长按、双击等行为。要使用GestureDetector也不复杂,参考如下过程。首先,需要创建一个GestureDetector对象并实现OnGestureListener接口,根据需要我们还可以实现OnDoubleTapListener从而能够监听双击行为。接着,接管目标View的onTouchEvent方法,在待监听View的onTouchEvent方法中添加如下实现:

boolean consume = mGestureDetector.onTouchEvent(event);
return consume;

做完了上面两步,我们就可以有选择地实现OnGestureListener和OnDoubleTapListener中的方法了,方法很多,但是并不是所有的方法都会被时常用到,在日常开发中,比较常用的有:onSingleTapUp(单击)、 onFling(快速滑动)、onScroll(拖动)、onLongPress(长按)和onDoubleTap(双击)。另外这里要说明的是,实际开发中,可以不使用GestureDetector,完全可以自己在View的onTouchEvent方法中实现所需的监听,这个就看个人的喜好了。这里有一个建议供读者参考:如果只是监听滑动相关的,建议自己在onTouchEvent中实现,如果要监听双击这种行为的话,那么就使用GestureDetector。

ScroIIer弹性滑动对象,用于实现View的弹性滑动。我们知道,当使用View的scrollTo/scrollBy方法来进行滑动时,其过程是瞬间完成的,这个没有过渡效果的滑动用户体验不好。这个时候就可以使用Scroller来实现有过渡效果的滑动,其过程不是瞬间完成的,而是在一定的时间间隔内完成的。Scroller本身无法让View弹性滑动,它需要和View的computeScroll方法配合使用才能共同完成这个功能。那么如何使用Scroller呢?它的典型代码是固定的,如下所示。

mScroller = new Scroller(getContext());

    private void smoothScrollBy(int dx, int dy) {
        mScroller.startScroll(getScrollX(), 0, dx, 0);
        invalidate();
    }
@Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();
        }
    }