《Android进阶之光》学习笔记——第三章 View体系与自定义View

前言

对于一个APP来说,与用户交互、将内容展示给用户,都是一个个View通过扩展实现的。View是Android所有控件的基类,我们平常所用的TextVew和ImageView都是继承自View的。
而用的LinearLayout、RelativeLayout和FrameLayout布局控件继承自ViewGroup,ViewGroup是View的组合,包含很多View和ViewGroup,而它包含的ViewGroup又可以包含View和ViewGroup,依次类推,形成一个View树。


而ViewGroup也是继承自View。

public abstract class ViewGroup extends View implements ViewParent,ViewManager{
...
}

坐标系

Android系统中有两种坐标系,分别为Android坐标系View坐标系

Android坐标系

在Android中将屏幕左上角的顶点作为Android坐标系的原点,这个原点向右是X轴正方向,向下是Y轴正方向。在触控事件中,使用(getRawX(),getRawY())获得的坐标也是Android坐标系的坐标。


View坐标系

                                          View坐标系

(1)View获取自身的宽和高

width=getRight()-getLeft();
height=getBottom()-getTop();
此外系统给我们提供了获取View宽和高的方法,getHeight()用来获取View自身的高度,getWidth()用来获取View自身的宽度。

源码如下:

public final int getHeight(){
return mBottom-mTop;
}

public final int getWidth(){
return mRight-mLeft;
}
(2)View自身的坐标

通过如下方法可以获得View到其父控件(ViewGroup)的距离;

getTop():获取View自身顶边到其父布局顶边的距离。

getLeft():获取View自身左边到其父布局左边的距离。

getRight():获取View自身右边到其父布局左边的距离。

getBottom():获取View自身底边到其父布局顶边的距离。

(3)MotionEvent提供的方法

假设View坐标系示意图中的圆点是触摸点,此外View和ViewGroup的点击事件都由onTouchEvent(MotionEvent event)方法来处理。MotionEvent在用户交互中作用重大,其内部提供了很多事件常量,比如ACTION_DOWN、ACTION_UP和ACTION_MOVE。此外,MotionEvent也提供了获取焦点坐标的各种方法。

getX():获取点击事件距离控件左边的距离,即视图坐标。

getY():获取点击事件距离控件顶边的距离,即视图坐标。

getRawX():获取点击事件距离整个屏幕左边的距离,即绝对坐标。

getRawY():获取点击事件距离整个屏幕顶边的距离,即绝对坐标。

View的滑动

基本思想:当点击事件传到View时,系统记下触摸点的坐标,手指移动时系统记下移动后触摸的坐标并算出偏移量,并通过偏移量来修改View的坐标。

View的6种滑动方式:

layout()
offsetLeftAndRight()与offsetTopAndBottom()
layoutParams
动画
scrollTo与scrollBy
Scroller

解析Scroller 

Scroller的原理:Scroller并不直接实现View的滑动,它需要配合View的computeScroll()方法。在computeScroll()中不断让View进行重绘,每次重绘都会计算滑动持续的时间,根据这个持续时间就能算出这次View滑动的位置,我们根据每次滑动的位置调用scrollTo()方法进行滑动,这样不断地重复上述过程就形成了弹性滑动。

View的事件分发机制

Activity构成

一个Activity包含一个Window对象,这个对象是由PhoneWindow来实现的。PhoneWindow将DecorView作为整个应用窗口的根View,而这个DecorView又将屏幕划分为两个区域:一个是TitleView,另一个是ContentView,而我们平常做应用所写的布局正是展示在ContentView中。

源码解析View的事件分发机制

当我们点击屏幕时,就产生了点击事件,这个事件被封装成了一个类:MotionEvent。而当这个MotionEvent产生后,那么系统就会将这个MotionEvent传递给View的层级,MotionEvent在View中的层级传递过程中就是点击事件分发。点击事件有三个重要方法,如下:

dispatchTouchEvent(MotionEvent ev)——用来进行事件分发。

onInterceptTouchEvent(MotionEvent ev)——用来进行事件的拦截,在dispatchTouchEvent()中调用,需要注意的是View没有提供该方法。

OnTouchEvent(MotionEvent ev)——用来处理点击事件,在dispatchTouchEvent()方法中进行调用。

View的事件分发机制

当点击事件产生后,事件首先会传递给当前的Activity,这会调用Activity的dispatchTouchEvent()方法,具体的事件处理工作交给DecorView,之后再由DecorView将事件处理工作交给根ViewGroup。

View的工作流程

View的工作流程,指的就是measure、layout和draw。其中measure用来测量View的宽和高,layout用来确定View的位置,draw则用来绘制View。
一个Activity包含一个Window对象,这个对象是由PhoneWindow来实现的。PhoneWindow将DecorView作为整个应用窗口的根View,通过ViewRootImpl的setView方法将DecorView加载到Window中。此外,通过ViewRootImpl的PerformTraveals使得ViewTree开始View的工作流程,方法内部分别执行performMeasure、performLayout和performDraw,在其方法的内部又分别调用View的measure、layout和draw方法。

自定义View

自定义View分为自定义View自定义ViewGroup自定义组合控件三大类。其中自定义View又分为继承系统控件(比如TextView)和继承View两种。自定义ViewGroup也分为继承ViewGroup和继承系统特定的ViewGroup(比如RelativeLayout)。而自定义组合控件就是多个控件组合起来成为一个新的控件,主要用于解决多次重复使用同一类型的布局。比如顶部标题栏及弹出的固定样式的Dialog,这些都是常用的,所以把它们所需要的控件组合起来重新定义成一个新的控件。


猜你喜欢

转载自blog.csdn.net/gislaozhang/article/details/78751031
今日推荐