一.View基础知识:
1.View的位置参数:
View的位置主要是由四个顶点来决定的,分别是top、left、right、bottom。top是左上角从坐标、left是右下角横坐标、right是右下角横坐标、bottom是右下角纵坐标。这里的坐标都是相对于View的父容器来说的。
获取方式:getLeft()、getRight()、getTop()、getBottom()。
2.MotionEvent和TouchSlop:
MotionEvent中的ACTION_DOWN-手指刚接触屏幕;ACTION_MOVE-手指在屏幕上移动;ACTION_UP-手指从屏幕上松开的一瞬间。
getX/getY和getRawX/getRawY的区别:getX/getY是相对于View左上角的横从坐标;getRawX/getRawY是相对于屏幕左上角的横纵坐标。
3.TouchSlop:是系统所能识别出来的最小滑动距离,这是个常量和所用的设备有关,获取方式为:ViewConfiguration.get(getContext()).getScaledTouchSlop()。
4.VelocityTracker、GestureDetector和Scroller:
VelocityTracker:速度追踪,用于手指在滑动过程中的速度,其包含水平和竖直速度
获取方式:在View的TouchEvent
VelocityTracker velocityTracker=VelocityTracker.obtain();
velocityTracker.addMovement(event);
velocityTracker.computeCurrentVelocity(1000);
int xVelocity=(int)velocityTracker.getX velocity();
int yVelocity=(int)velocityTracker.getY velocity();
GestureDetector:手势检测检测用户的单击、滑动、长按、双击等行为。
使用:首先创建一个GestureDetector对象并实现OnGestureListener接口,
GestureDetector: mGestureDetector:=new GestureDetector:(this);
mGestureDetector:.setIsLongPressEnabled(false);
Scroller:弹性滑动对象,与View中的scrollTo/ScrollBy是瞬间完成的,Scroller是无法完成View的弹性滑动的,需要和view中的computeScroll配合使用才能完成。
使用:
Scroller scroller=new Scroller(mContext);
private void smoothScrollTo(int destX,int destY){
int scroll =getScrollX();
int delta=destX-scrollX;
mScroll.startScorll(scrollX,0,delta,0,0,1000);
inalidate();
}
@Override
public void computerScroll(){
if(mScroll.computerScrollOffer()){
scrollTo(mScroller.getCurrX(),mScroller.getCurrY();
postInvaildate();
)
}
}
二、View的事件分发机制:
1.dispatchTouchEvent(MotionEvent ev):用来进行事件分发。如事件能够传递给当前View,那么此方法一定会被调用,返回结果受当前view的onTouchEvent和下级的dispatchTouchEvent方法的影响。表示是否消耗当前的事件。
2.onInterceptTouchEvent(MotionEvent ev):用来判断是否拦截某个事件,如view拦截某个事件,那么在同一个事件序列中,此方法不会被再次调用,返回结果表示是否拦截当前事件。
3.onTochEvent(MotionEvent ev):在dispatchTouchEvent方法中调用,用来点击事件,返回结果表示是否消耗当前事件,如不消耗,则在同一个事件序列中,当前view无法再次接收到事件。
事件的传递规则:
对于一个根ViewGroup来说,点击事件产生之后,首先会传递给dispatchTouchEvent,这时dispatchTouchEvent会执行,如ViewGroup的onInterceptTouchEvent方法
返回为true就表示被拦截事件就会交给这个ViewGroup处理即onTouchEvent会被调用;如onInterceptTouchEvent返回为false表示不拦截当前事件,这时当前事件就会继续传递
给子view,接着子View的dispatchTouchEvent方法被调用,如此反复直到事件最终被处理。
当一个view需要处理事件时:如它设置了OnTouchListener,那么OnTouchListener中的OnTouchListener,onTouch方法会被调用。这时事件的处理还要看onTouch的返回值,如返回false则当前的onTouchEvent方法会被调用,如返回true则onTouchEvent不会被调用。
优先级:OnTouchListener>onTouch>OnClickListener.
事件传递顺序:当一个事件产生后顺序是:Activity->Window->View。
事件传递过程是由外向内的,事件总是先是传递给父View,然后再由父View分发给子View,通过requestDisallowInterceptTouchEvent方法可以在子View中干预父View的事件
分发过程,但是ACTION_DOWN事件除外。
三、View的绘制流程:
1.View的绘制是从ViewRoot的performTravesals方法开始的,measure、layout、draw三个过程才能最终讲一个View绘制出来。
measure过程决定View的宽高、measure完成之后,可以通过getMeasuredWidth和getMeasuredHeight方法最终获取View测量的宽高;
layout过程决定View的四个顶点的坐标和实际的宽高,完成之后通过getTop、getBottom、getLeft、getRight来拿到View的四个定点的位置,也可以通过getWidth、getHeight来拿到View的最终宽高;
draw过程决定View的显示。
2.MeasureSpec:代表一个32位的int值,高2位代表SpaceSize,SpaceMode代表测量模式:SpaceMode的三种模式
UNSPECIFIED:父容器不对View有任何限制,要多大给多大;
EXACILY:父容器已经检测出View所需的精确大小,这个时候View的最终大小就是SpaceSize;
AT_MOST:父容器指定一个可用的大小即SpaceSize,View大小不能超过这个值。
3.MeasureSpec和LayoutParams对应的关系:在设置LayoutParams后,在View的测量的时候,系统会将LayoutParams在父容器中的约束下转换成对用的MeasureSpec,然后在根据这个MeasureSpec来确定好View测量后的宽高。