[置顶] Android开发艺术探索总结之View篇
2016-11-05 12:32
441 查看
Android开发艺术探索总结之View篇
View的基础知识
什么是View
View是Android中所有控件的基类,可以说View是一种界面层的控件的一种抽象,它代表了一个控件,除了View还有ViewGroup,它被称为控件组,言外之意ViewGroup内部包含了许多控件,即一组View,在Android设计中,ViewGroup也是继承自View,这意味着View本身就可以是单个控件也可以是多个控件组成的一组控件,通过这种关系就形成了View树的结构,这跟Web前端中的DOM树概念类似View的位置参数
View的位置主要由它的四个顶点决定,分别对应于View的四个属性:top,left,right,bottom,其中top是左上角纵坐标,left是左上角横坐标,right是右下角横坐标,bottom是右下角纵坐标,不过这些都是相对于View的父容器来说的因为它是一种相对坐标,如下图,在Android中,x轴,y轴的正方向对应为右下
因此可以得到View的宽高跟位置的关系
width = right - left height = bottom - top
调用View的getWidth,getHeight的时候,源码就是这样计算View的宽高的,源码如下:
/** * Return the width of the your view. * * @return The width of your view, in pixels. */ @ViewDebug.ExportedProperty(category = "layout") public final int getWidth() { return mRight - mLeft; } /** * Return the height of your view. * * @return The height of your view, in pixels. */ @ViewDebug.ExportedProperty(category = "layout") public final int getHeight() { return mBottom - mTop; }
在代码中如何获取View的这些参数?
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也为它提供了set/get方法,对应关系如下:
x = left + translationX; y = top + translationY;
注意: View在平移的过程中,top和left表示的是原始左上角的位置信息,并且不会改变!此时改变的是x,y,translationX,translationY这四个参数
MotionEvent和TouchSlop
MotionEvent
手指接触屏幕后所产生的一系列事件中,典型的事件类型有:ACTION_DOWN - 手指刚接触到屏幕
ACTION_MOVE - 手指在屏幕上移动
ACTION_UP - 手指从屏幕上松开的一瞬间
正常情况下,一次手指触摸屏幕的行为会触发一系列的点击事件,如:
点击屏幕后随即离开屏幕,事件序列为DOWN -> UP;
点击屏幕后滑动一段距离再松开,事件序列为DOWN -> MOVE -> … ->MOVE -> UP
上述三种情况是典型的事件序列,通过MotionEvent对象我们可以得到点击事件发生的x,y坐标,系统提供了两组方法:
getX()/getY()和
getRawX()/getRawY(),他们的区别为getX()/getY()返回的是相对于
当前View左上角的x和y坐标,而getRawX()/getRawY()返回的是相对于
手机屏幕左上角的x和y坐标
ToushSlop
TouchSlop是系统所能识别出的滑动最小距离,当手指在屏幕上滑动时,如果两次滑动之间的距离小于这个常量,那么系统就不认为它是滑动。这是一个常量,和设备有关,在不同设备上这个值可能不同,如何在代码中获取这个常量?
int touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
这个常量存在的目的是为了让我们在处理滑动时,可以利用它来做一些过滤,比如当两次滑动事件的滑动距离小于这个值,我们就可以认为未达到滑动距离的临界值,因此可以认为它们不是滑动,达到更好的用户体验。
源码中对应的位置:frameworks/base/core/res/res/values/config.xml
<!-- Base "touch slop" value used by ViewConfiguration as a movement threshold where scrolling should begin. --> <dimen name="config_viewConfigurationTouchSlop">8dp</dimen>
VelocityTracker和GestureDetector
VelocityTracker
速度追踪,用于追踪用户手指在滑动过程中的速度,包括水平和竖直方向的速度。使用方法:在View的onTouchEvent方法追踪当前单击事件的速度:
@Override public boolean onTouchEvent(MotionEvent event) { VelocityTracker velocityTracker = VelocityTracker.obtain(); velocityTracker.addMovement(event); return super.onTouchEvent(event); }
接下来,当我们想知道当前的滑动速度时,可以采用以下方法来获取当前速度
@Override public boolean onTouchEvent(MotionEvent event) { VelocityTracker velocityTracker = VelocityTracker.obtain(); velocityTracker.addMovement(event); switch (event.getAction()) { case MotionEvent.ACTION_MOVE: velocityTracker.computeCurrentVelocity(1000); int xVelocity = (int) velocityTracker.getXVelocity(); int yVelocity = (int) velocityTracker.getYVelocity(); Log.e(TAG, "xVelocity = " + xVelocity + " yVelocity = " + yVelocity); break; case MotionEvent.ACTION_UP: velocityTracker.clear(); velocityTracker.recycle(); break; } return true; }
注意:
第一:在获取速度之前必须先计算速度,必须先调用
velocityTracker.computeCurrentVelocity(1000);
第二:这里的速度是指一段时间内手指所滑过的像素数,比如将时间间隔设置为1000ms,手指在这个时间内水平滑动了100像素,那么水平速度为100,当然速度可能为负数,手指向左滑动时,速度值为负数,速度的计算公式:
速度 = (终点位置 - 起点位置) / 时间段
根据公式再加上Android系统的坐标系,手指逆着坐标系的正方向滑动,所产生的速度就为负值。另外,computeCurrentVelccity(int units), units代表时间单元或者说是时间间隔,单位为ms,计算速度时得到的速度就是在这个时间间隔内手指在水平或竖直方向上所滑动的像素数。
最后,不需要时该对象时,需要手动回收:
velocityTracker.clear(); velocityTracker.recycle();
GestureDetector
手势检测,用户辅助检测用户的单击,滑动,长按,双击等行为,使用流程如下:首先创建一个GestureDetector对象,并实现OnGestureListener
GestureDetector mGestureDetector = new GestureDetector(getContext(), new GestureDetector.OnGestureListener() { @Override public boolean onDown(MotionEvent e) { return false; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; } @Override public void onLongPress(MotionEvent e) { } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return false; } });
然后接管目标View的onTouchEvent
@Override public boolean onTouchEvent(MotionEvent event) { boolean consume = mGestureDetector.onTouchEvent(event); return consume; }
实现双击:
GestureDetector mGestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener(){ @Override public boolean onDown(MotionEvent e) { return true; } @Override public boolean onDoubleTap(MotionEvent e) { Log.e(TAG,"onDoubleTap"); return super.onDoubleTap(e); } });
OnGestureListener
方法名 | 描述 |
---|---|
onDown | 手指轻轻触摸屏幕的一瞬间,由1个ACTION_DOWN触发 |
onShowPress | 手指轻轻触摸屏幕,尚未松开,由1个ACTION_DOWN触发,跟onDown的区别在于,它强调的是没有松开或者拖动的状态 |
onSingleTapUp | 手指(轻轻触摸屏幕后)松开,伴随着1个ACTION_UP触发,这是单击行为 |
onScroll | 手指按下屏幕并拖动,由1个ACTION_DOWN多个ACTION_MOVE触发,,这是拖动行为 |
onLongPress | 用户按着屏幕不放,即长按 |
onFling | 用户按下屏幕,快速滑动后松开,由1个ACTION_DOWN,多个ACTION_MOVE和1个ACTION_UP触发,这是快速滑动行为 |
方法名 | 描述 |
---|---|
onSingleTapConfirmed | 严格的单击行为,与onSingleTapUp的区别,如果触发了onSingleTapConfirmed,那么后面不可能再紧跟着另一个单击行为,即这只可能是单击,不可能是双击中的任意单击 |
onDoubleTap | 双击,由两个连续的单击组成,它不可能和onSingleTapConfirmed共存 |
onDoubleTapEvent | 表示发生了双击行为,在双击期间,ACTION_DOWN、ACTION_MOVE和ACTION_UP都会触发此回调 |
相关文章推荐
- Android开发艺术探索——第三章View事件体系读书笔记
- Android——自定义View(学习Android开发与艺术探索)
- 开发艺术探索--Android的View事件体系
- Android开发艺术探索--第二章IPC机制(4)之Binder连接池以及IPC总结
- 读书笔记-Android开发艺术探索-第3章-View的事件体系
- Android开发艺术探索——第四章View的工作原理
- Android艺术开发探索第三章——View的事件体系(上)
- Android view的工作原理(Android开发艺术探索随笔)
- Android艺术开发探索第三章————View的事件体系(下)
- Android艺术开发探索学习 之 测量view的宽高 以及 动态设置View的位置
- Android开发艺术探索学习-View的事件分发机制(二)
- Android开发艺术探索--第一章生命周期和启动方式总结(1)
- Android开发艺术探索学习-View的基本知识
- 【读书笔记】【Android 开发艺术探索】第3章 View 的事件体系
- Android——View的事件分发机制(学习Android开发艺术探索)
- Android开发艺术探索——学习笔记_View事件体系
- Android开发艺术探索(三)——View的事件体系
- Android开发艺术探索学习-View的事件分发机制(一)
- Android开发艺术探索学习-View的滑动
- Android开发艺术探索<View的点击事件触发过程>