Android自定义View学习(一):实心圆

1. View的基础知识

1. 什么是View

View是Android中所有控件的基类,View的本身可以是单个空间,也可以是多个控件组成的一组控件,即ViewGroup,ViewGroup继承自View,其内部可以有子View,这样就形成了View树的结构。


2. View的位置参数

View的位置主要由它的四个顶点来决定,即它的四个属性:top、left、right、bottom,可用来分别表示View左上角的坐标点( top,left) 以及右下角的坐标点( right,bottom) 。

View的位置参数
这四个参数可以由以下方式获取:

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

根据这张图,我们可以得到一些简单的换算:

int width = right - left;    //宽度
int height = bottom - top;   //高度

Android3.0后,View增加了x、y、translationX和translationY这几个参数。其中x和y是View显示时左上角相对于父容器的坐标:

int x = getX();
int y= getY();

getX( ) 和 getLeft( ) 得到的值的区别是:

  • left:View的左边相对于父View左边的距离。这个值不会随着View的属性(transitionX和X)改变。
  • View在layout的时候,会调用setFrame函数来改变left的值。客户端可以直接调用setLeft( )来改变left值。
  • left值改变后,View的大小也会改变。因为View的大小是right - left;
  • x: View实际显示位置的左边相对于父View左边的距离。它的值是 translationX + left;
  • tanslationX:View 相对于left的位移。属性动画改变的是x和translationX的值,没有改变left的值。

他们之间的换算关系如下:

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

来个更详细的图:

View的完整位置参数

上图很好的说明了每个方法获得的坐标值或者距离代表的意义,图中有三个黑色的框框,最外层是手机屏幕,中间层是ViewGroup,最内层是ViewGroup中的View。

其实上图中标注的方法可以分为两类,一类是View提供的方法,一类是MotionEvent提供的方法:

扫描二维码关注公众号,回复: 2658847 查看本文章

1.View提供的获取的坐标以及距离的方法:

getX();             //获取到的是view显示位置的左边到其父布局左边的距离
getY();             //获取到的是view显示位置的顶边到其父布局顶边的距离
getTop();           //获取到的是view自身的顶边到其父布局顶边的距离
getLeft();          //获取到的是view自身的左边到其父布局左边的距离
getRight();         //获取到的是view自身的右边到其父布局左边的距离
getBottm();         //获取到的是view自身的底边到其父布局顶边的距离

2.MotionEvent提供的方法:

getX();             //获取点击事件距离控件左边的距离,即视图坐标
getY();             //获取点击事件距离控件顶边的距离,即视图坐标
getRawX();          //获取到的是点击事件距离整个屏幕左边的距离,即绝对坐标
getRawY();          //获取到的是点击事件距离整个屏幕顶边的距离,即绝对坐标
getScrollY();       //获取 视图坐标原点 到 视图 滚出屏幕 的距离
getScrollX();       //类似 同上

3. View的工作原理

ViewRoot的实现是 ViewRootImpl 类,是连接WindowManager和DecorView的纽带,View的三大流程( mearsure、layout、draw) 均是通过ViewRoot来完成。当Activity对象被创建完毕后,会将DecorView添加到Window中,同时创建 ViewRootImpl 对象,并将ViewRootImpl 对象和DecorView建立连接,源码如下:

root = new ViewRootImpl(view.getContext(),display);
root.setView(view,wparams, panelParentView);

看一张图

View的绘制流程

View的绘制流程是从ViewRoot的performTraversals()方法开始的,然后是:
- measure( ):用来测量View的宽高 ;
- layout( ):来确定View在父容器中的位置 ;
- draw( ):负责将View绘制在屏幕上。

performTraversals()会依次调用 performMeasure( ) 、 performLayout( ) 和performDraw( ) 三个方法,这三个方法分别完成顶级View的measure( )、layout( )和draw( )这三大流程。其中 performMeasure( ) 中会调用 measure( ) 方法,在 measure( ) 方法中又会调用 onMeasure( ) 方法,在 onMeasure ( )方法中则会对所有子元素进行measure过程,这样就完成了一次measure过程;子元素会重复父容器的measure过程,如此反复完成了整个View数的遍历。另外两个过程同理。

  • Measure完成后, 可以通过getMeasuredWidth( )、getMeasureHeight( )
    方法来获取View测量后的宽/高。特殊情况下,测量的宽高不等于最终的宽高,详见后面。

  • Layout过程决定了View的四个顶点的坐标和实际View的宽高,完成后可通过 getTop( ) 、 getBottom( ) 、 getLeft( ) 和 getRight( ) 拿到View的四个定点坐标。


4. View的MeasureSpec

猜你喜欢

转载自blog.csdn.net/cvStronger/article/details/78360295