View的基础知识

View的事件体系整体上理解还是比较简单的,但是有很多的细节,这些细节很容易被忽略掉。所以写下这篇文章来加深记忆。

1、View事件的相关基础

View是一种界面层的控件的一种抽象,它代表了一个控件。
ViewGroup为控件组。
View中也可以包含多个控件,形成控件树。
ImageButton是一个View,LinearLayout是一个View,也是一个ViewGroup。

2、View的坐标以及高

2.1视图坐标系
在Android系统中,一个子View在ViewGroup中显示的区域由top、right、bottom、left四个属性确定。它们分别确定四条边,如下图所示:

子View所在的区域

这四个参数我们可以通过如下方法得到:

1
2
3
4
5
6
//假设v是个View实例
//View v=···;
int top = v.getTop();
int right = v.getRight();
int bottom = v.getBottom();
int left = v.getLeft();

拿到这四个参数以后,我们可以计算处宽和高

1
2
int width=right-left
int height=bottom-top

我们知道在Android3.0之前,是不能用属性动画的。只能用补间动画。而补间动画所做的动画效果只是将View的显示转为图片。然后给这个图片做透明的,平移,旋转,缩放等效果。这带来的问题是,View所在的区域类并没有发生变化,变化的是个“幻影”而已。也就是说,在Android3.0之前,要将View区域发生变化,就得改变top、left、right、bottom。如果是我们想要将动画的实际位置发生变化的时候,并且要兼容3.0之前的软件,我们就从3.0开始,加入了几个新的参数:x,y,translationX,translationY。

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

这样,如果我们想要移动View,只需要改变translationX和translationY就可以了。top和left不会发生变化。也可以使属性动画去改变translationX和translationY。

2.2、Android坐标系(以屏幕的左上角为原点)

属于MotionEvent的

1
2
getX(),getY() 相当于父容器
getRawX(),getRawY() 相当于屏幕的

##3、MotionEvent和TouchSlop

3.1 MotionEvent

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

  • ACTION_DOWN–手指刚接触屏幕
  • ACTION_MOVE–手指在屏幕上滑动
  • ACTION_UP—手指从屏幕上松开的那一瞬间

正常情况下,一次手指接触屏幕的行为会发生一系列的点击事件,考虑下面几种情况:

  • 点击屏幕后离开松手 事件的序列是DOWN–UP
  • 点击屏幕后移送一圈,然后松手 事件的序列是 DOWN–MOVE….—-UP
3.2、TouchSlop

TouchSlop是系统所能识别处的被认为是滑动最小的距离。换句话说,当手指在屏幕上滑动的时候,如果两次滑动之间的距离小于这个常量,那么系统就不认为你是在进行滑动操作。原因很简单:滑动的距离太短,系统不认为它是滑动的。这个值是一个常量,和设备有关。一般在源码里面找到。frameworks/base/core/res/res/values/config.xml文件中

1
<dimen name="config_viewConfigurationTouchSlop">8dp</dimen>

##4、VelocityTracker速度追踪

用于追踪手指在滑动过程中的速度,包括水平和竖直
它所谓的滑动速度指的就是一段时间内手指划过的像素数,比如假设时间间隔为1s,速度就是指手指在水平方向从左向右划过的100像素时,速度就是100,那如果向左滑动时,速度就是负值了。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 首先在View的onTouchEvent方法中获取追踪速度的对象
VelocityTracker velocityTracker = VelocityTracker.obtain();
// 将追踪速度对象与事件绑定起来:
velocityTracker.addMovement(event);
// 获取速度之前先计算速度,这一句不可缺:
velocityTracker.computeCurrentVelocity(1000); //1S时间内
// 分别计算水平和竖直速度:
int xVelocity = (int) velocityTracker.getXVelocity();
int yVelocity = (int) velocityTracker.getYVelocity();

// 不需要使用它的时候,来重置和回收:
velocityTracker.clear();
velocityTracker.recycle();

5、GestureDetector手势检测

用户辅助检测用户的单击,滑动,长按,双击等行为
一般情况下,我们知道View类有个View.OnTouchListener内部接口,通过重写它的onTouch(View v,MotionEvent event)方法,我们可以处理一些touch事件,但是这个方法太过于简单,如果需要处理一些复杂的手势,用这个接口就会很麻烦(因为我们要根据用户触摸的轨迹去pan’duan是什么手势)。

onTouch与onTouchEvent的区别:
1、onTouch
onTouch方法是viewOnTouchListener()接口定义的方法。
当一个View绑定了OnTouchListener后,当touch事件触发时,就会调用onTouch方法
(当把手放到View上后,onTouch方法被一遍一遍的调用)
2、onTouchEvent
onTouchEvent是override的Activity的方法
重新Activity的onTouchEvent方法后,当屏幕有touch事件的时候,此方法就会被调用
(当手放到Activity上时,onTouchEvent方法就会一遍一遍的被调用)
3、touch事件的传递
在一个Activity里面放置一个TextView的实例tv,并且这个tv的属性设定为march_parent。在这种情况下,当我们的手放置在屏幕上的时候,首先会是tv响应touch事件,执行onTouch方法。
当返回的是true的时候,就表示touch事件被onTouch方法处理完毕以后,是不会把这个事件传递给Activity的,也就是说不会onTouchEvent方法不会被调用。
(当把手放置在屏幕上,onTouch方法会被一遍一遍的被调用)

当onTouch返回的是false的时候,表示touch事件没有被tv完全处理,onTouch返回以后,touch事件会被传递给Activity,onTouchEvent方法会被调用

上面啰嗦了那么多,主要就是为了给下面做一些区别,加深我们的印象

GesturDetector主要是通过它的onTouchEvent方法实现不同手势的识别。虽然能识别手势,但是不同的手势要怎么处理是程序员所要干的事情

View的事件体系
Android 手势检测实战 打造支持缩放平移的图片预览效果(上)
Android 手势检测实战 打造支持缩放平移的图片预览效果(下)
坚持原创技术分享,您的支持将鼓励我继续创作!