标签:style gre 转换 手动 ack 获取 att 自定义属性 man
4.1 ViewRoot和DecorView
ViewRoot对应于ViewRootImplement类,它是连接WindowManager和DecorView的纽带,View的三大流程均是通过ViewRoot来完成的.
在ActivityThread中,当Activity对象被创建完毕后,会将DecorView添加到Window中,同时会创建ViewRootImpl对象,并将ViewRootImpl对象和DecorView建立关联
View的绘制流程是从ViewRoot的performTraversals方法开始的,它经过measure,layout和draw三个过程来将一个View绘制出来
4.2 MeasureSpec
MeasureSpec参与了View的measure过程,在很大程度上决定了一个view的尺寸规格.
4.2.1 概念
MeasureSpec代表是一个32位int值,高2位代表SpecMode,低30位代表SpecSize,SpecMode是指测量模式,而SpecSize是指在某种测量模式下的规格大小.
SpecMode有三类:
4.2.2 MeasureSpec和LayoutParams的对应关系
在View测量的时候,系统会将LayoutParams在父容器的约束下转换成对应的MeasureSpec,然后再根据这个MeasureSpec来确定View测量后的宽/高.
4.3 View的工作流程
View的工作流程主要是指measure,layout,draw这三大流程,即测量,布局和绘制,其中measure确定View的测量宽/高,layout确定View的最终宽高和四个顶点的位置,而draw则将View绘制到屏幕.
4.3.1 measure过程
1. View的measure过程
View的measure过程由其measure方法来完成,measure方法是一个final类型的方法,子类不能重写此方法,在View的measure方法中会去调用View的onMeasure方法
2. ViewGroup的measure过程
除了完成自己的measure过程之外,还会遍历去调用所有子元素的measure方法,各个子元素再递归去执行这个过程.
ViewGroup是一个抽象类,因此它没有重写View的onMeasure方法,但是提供了measureChildren的方法.
measureChild的思想就是取出子元素的LayoutParams,然后再通过getChildMeasureSpec来创建子元素的MeasureSpec,接着将MeasureSpec直接传递给View的measure方法进行测量.
如果它的布局中高度采用的是match_parent或者具体数值,那么它的测量过程和View一致,即高度为SpecSize;如果它的布局中高度采用的是wrap_content,那么它的高度是所有子元素所占用的高度综合,但是仍然不能超过它的父容器的剩余空间.
measure完成之后,可以通过getMeasuredWight/Height方法就可以正确的取到View的测量宽/高.
onWindowFocusChanged方法:View已经初始化完毕,宽/高已经准备好了,这个时候去获取宽/高
view.post(runnable)方法:通过post可以将一个runnable投递到消息队列的尾部,然后等待Looper调用次runnable的时候,View也已经初始化好了.
ViewTreeObserver:可以使用OnGlobalLayoutListener这个接口,当View树的状态发生改变或者View树内部的View的可见性发生改变,onGlobalLayout方法方法将被回调.
view.measure:通过手动对View进行measure来得到View的宽/高
4.3.2 layout过程
Layout的作用是ViewGroup用来确定子元素的位置,当ViewGroup的位置被确定后,它在onLayout中会遍历所有的子元素并调用其layout方法,在layout方法中onLayout方法又会被调用.
layout方法确定View本身的位置,而onLayout方法则会确定所有子元素的位置
layout方法大致流程:首先会通过setFrame方法来设定View的四个顶点的位置,接着调用onLayout方法,用途是父容器确定子元素的位置,和onMeasure方法类似
4.3.3 draw过程
4.4 自定义View
4.4.1 自定义View的分类
4.4.2 自定义View须知
4.4.3 自定义View
自定义属性:
第一步:在values目录下面创建自定义属性的XML(一般以attrs_开头的文件名)
<?xml version="1.0" encoding="UTF-8"?> <resources> <declare-styleable name="CircleView"> <attr name="circle_color" format="color"/>//定义一个格式为"color"的属性 </declare-styleable> </resources>
第二步:在View的构造方法中解析自定义属性的值并做相应处理.
public CircleView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypeArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleView); mColor = a.getColor(styleable.CircleView_circle_color, Color.RED); a.recycle(); init(); }
加载自定义属性集合CircleView,接着解析CircleView属性集合中的circle_color属性
如果在使用时没有指定circle_color这个属性,那么就会选择红色作为默认的颜色值.
解析完成之后通过recycle方法来实现资源
第三步:在布局文件中使用自定义属性
<LinearLayout xmlns:android="http://schemes.android.com/apk/res/android" xmlns:app="http://schemes.android.com/apk/res-auto"//必须在布局文件中添加schemas声明 android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ffffff" android:orientation="vertical"> <com.example.CircleView android:id="@+id/circleView1" android:layout_height="wrap_content" android:layout_height="100dp" android:layout_margin="20dp" app:circle_color="@color/light_green" android:padding="20dp" android:background="#00000"/> </LinearLayout>
其它的View继承也是基于这种思路,measure,layout,draw.
标签:style gre 转换 手动 ack 获取 att 自定义属性 man
原文地址:http://www.cnblogs.com/JingQ/p/6175720.html