View的事件体系-View基础知识

作者: 墨白历险记 | 来源:发表于2018-10-22 14:24 被阅读29次

位置参数

View的位置主要由它的四个顶点来决定,分别对应于View的四个属性:top、left、right、bottom.
其中top是左上角的纵坐标,left是左上角的横坐标,right是右下角的横坐标,bottom是右下角的纵坐标.(注:这些坐标都是相对于父容器所说,为相对坐标)

image.png

View的宽高和坐标的关系:

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

在代码中获取四个位置参数:

top = getTop();
left = getLeft();
right = getRight();
bottom = getBottom();

从3.0之后开始,Android增加了几个参数:x、y、translationX、translationY,并且都是相对父容器的的坐标,其中x和y是View左上角的坐标.translationX和translationY是View左上角相对于父容器的偏移量,且默认值都为0.

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

注:在View的平移过程中,top和left始终表示的是其原始左上角的位置信息,不会发生改变,改变的是x、y、translationX和translationY.

MotionEvent

典型事件

手指接触屏幕后所产生的一系列事件中,比较重要的有:

  • ACTION_DOWN 手指刚接触屏幕
  • ACTION_MOVE 手指在屏幕上移动
  • ACTION_UP 手指抬起的一瞬间
常见事件序列
  • 点击屏幕后抬起 DOWN -> UP
  • 点击屏幕后滑动后再抬起 DOWN -> MOVE -> UP
事件信息

通过MotionEvent对象我们可以得到点击事件发生的x和y坐标.

  • getX()、getY() 相对于当前View左上角.
  • getRaw()、getY() 相对于手机屏幕左上角

TouchSlop

什么是TouchSlop

TouchSlop是系统所能识别出的最小滑动距离.如果手指在屏幕上滑动小于该距离则系统无法将该动作认定为滑动.
这是一个常量,与设备有关,在不同的设备上这个值可能不同.

获取TouchSlop
int touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
使用场景

当我们在处理滑动时,可以使用这个常量来进行过滤,当滑动距离小于该值,我们可以认为未达到滑动距离的临界值,不认为它是一次有效的滑动.

VelocityTracker

速度追踪,用于追踪手指在滑动过程中的速度,包括水平速度和竖直方向的速度.

使用过程

在View的onTouchEvent方法中追踪当前单击事件的的速度:

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        VelocityTracker tracker = VelocityTracker.obtain();
        tracker.addMovement(event);
        tracker.computeCurrentVelocity(1000);//一个时间单元或时间间隔,单位为毫秒
        float xVelocity = tracker.getXVelocity();
        float yVelocity = tracker.getYVelocity();
        return super.onTouchEvent(event);
    }

注:获取速度之前必须先计算速度,即getXVelocity和getYVelocity之前必须要调用computeCurrentVelocity方法.这里的速度是指一段时间内手指所滑过的像素数,比如将时间设置为1000ms时,在1s内,手指在水平方向从左向右滑过100像素,那么水平速度就是100.且速度可以为负数,当手指从右向左滑动时,水平方向速度即为负值.
计算公式:

速度 = (终点位置 - 起点位置) / 时间段

当不需要使用后需重置回收.

 tracker.clear();
 tracker.recycle();

GestureDetector

手势检测,用于辅助检测用户的单击、滑动、长按、双击等行为.

使用方式

创建GestureDetector对象并实现OnGestureListener接口,如果需要监听双击行为还可以实现OnDoubleTapListener接口.并接管onTouchEvent方法.

public class SeanView extends View implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener {

GestureDetector detector = new GestureDetector(this);
detector.setIsLongpressEnabled(false);//解决长按屏幕后无法拖动问题
  
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean consume = detector.onTouchEvent(event);
        return consume;
    }
}
方法介绍
  • OnGestureListener
    • onDown 手指接触屏幕的瞬间
    • onShowPress 手指接触屏幕的瞬间,尚未松开或拖动
    • onSingleTapUp 单击
    • onScroll 拖动
    • onLongPress 长按
    • onFling 快速滑动
  • OnDoubleTapListener
    • onDoubleTap 双击 与onSingleTapConfirmed互斥
    • onSingleTapConfirmed 单击且后续无单击行为
    • onDoubleTapEvent 双击

Scroller

用于实现View的弹性滑动.Scroller本身无法让View弹性滑动,它需要和computeScroll方法配合使用.

 private Scroller scroller = new Scroller(getContext());

    private void smoothScrollTo(int destX, int destY) {
        int scrollX = getScrollX();
        int delta = destX - scrollX;
        scroller.startScroll(scrollX, 0, delta, 1000);
        invalidate();
    }

    @Override
    public void computeScroll() {
        if (scroller.computeScrollOffset()) {
            scrollTo(scroller.getCurrX(), scroller.getCurrY());
            postInvalidate();
        }
    }

相关文章

网友评论

    本文标题:View的事件体系-View基础知识

    本文链接:https://www.haomeiwen.com/subject/fbeleftx.html