前言
自定义控件,一直感觉是很高深的技术,现在准备入门,攻克它
- 自定义view的生命周期
先来打印一下它的生命周期方法
![T@L{SRPMP%0V6]24Y%5Z(~4.png](http://upload-images.jianshu.io/upload_images/6010233-efe93db1679cdff5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
看过之后,也就知道了,为什么在activity的oncreate()方法里,不能直接得到view的宽高,因为还没开始测量
当activity被销毁,自定义view也就死亡
在activity的onResume()回调后,自定义view才添加到window,回调onAttachedToWindow(),才开始测量 -
一个问题
在布局文件中,自定义view的宽高都是写的wrap_content,但是绘制出来却是match_parent的效果
查看super.onMeasure()源码,发现当测量模式是AT_MOST和EXACTLY,取的都是指定的值
public static int getDefaultSize(int size, int measureSpec) {
int result = size;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
result = size;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
所以呢,如果我们的自定义view,在布局文件中写的是wrap_content,那么我们要重写onMeasure()方法,来指定测量的size(宽,高)
-
一个问题
为什么会调用三次onMeasure(),两次onLayout(),一次onDraw()???
一些概念
- Window 类
位于 /frameworks/base/core/java/android/view/Window.java。该类是一个抽象类,提供了绘制窗口的一组通用API。可以将之理解为一个载体,各种View在这个载体上显示。
- PhoneWindow类
位于/frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindow.java。该类继承于Window类,是Window类的具体实现,即我们可以通过该类具体去绘制窗口。并且,该类内部包含了一个DecorView对象,该DectorView对象是所有应用窗口(Activity界面)的根View。 简而言之,PhoneWindow类是把一个FrameLayout类即DecorView对象进行一定的包装,将它作为应用窗口的根View,并提供一组通用的窗口操作接口。
- DecorView类
该类是PhoneWindow类的内部类。该类是一个FrameLayout的子类,并且是PhoneWindow的子类,该类就是对普通的FrameLayout进行功能的扩展,更确切点可以说是修饰(Decor的英文全称是Decoration,即“修饰”的意思),比如说添加TitleBar(标题栏),以及TitleBar上的滚动条等 。最重要的一点是,它是所有应用窗口的根View 。
打个不恰当比喻吧,Window 类相当于一幅画(抽象概念,什么画我们未知) ,PhoneWindow 为一副齐白石先生的山水画(具体概念,我们知道了是谁的、什么性质的画),DecorView 则为该山水画的具体内容(有山、有水、有树,各种界面)。DecorView呈现在PhoneWindow上。