本帖最后由 Android_Robot 于 2017-2-28 15:04 编辑
自定义控件常用方法总结(上)
自定义控件中除了绘制流程涉及到的测量布局绘制的api, 还有一些api使用的也比较频繁,这里做了一下总结,也请同学们补充或纠正。
inflateinflate方法常常用来解析一个xml布局文件,在自定义组合式控件中常常使用,使用的姿势包括:
View.inflate(context, resource, root)LayoutInflater.
from(getContext()).inflate(resource, root);
而View.inflate其实还是调用的LayoutInflater去解析一个xml:
public static View inflate(Context context, int resource, ViewGroup root){ LayoutInflater factory = LayoutInflater.from(context);
return factory.inflate(resource, root);}
所以这两种姿势没啥区别,这里来讨论一下inflate(resouce, root)的返回值,参数resource是布局资源,root是传入的一个根节点。如果root传入一个null,inflate就会解析resource对应的xml,返回这个xml中的根节点,如果root传入不为null,inflate会解析这个xml布局并且添加到根节点root下,然后返回根节点root。
另外还有带三个参数的inflate方法: inflate(int resource, ViewGroup root, boolean attachToRoot)
这里多了一个参数attachToRoot,如果root为null,则返回解析后的xml布局中的根节点;如果root不为null,attachToRoot为true,inflate会解析这个xml布局并且添加到根节点root下,然后返回根节点root;如果root不为null,attachToRoot为false,inflate会解析这个xml布局但不会添加到根节点root下,然后返回解析后的xml布局中的根节点,这时候root的作用只是为xml中的根节点提供布局参数的属性,因为xml中的根节点不知道自己的父容器是谁,所以如果没有人给它提供的话,它的布局参数就会失效。
onFinishInflateonFinishInflate是当所有的孩子都解析完后的一个调用。比如我们自定义一个ViewGroup,想要去找到孩子做一些设置,这时候如果在自定义ViewGroup的构造函数去findViewById的话,会返回一个null,因为此时孩子还没有解析好,也就是还没有生出来。这时候我们可以去覆写onFinishInflate,当孩子解析好后再去find。
requestLayout关于requestLayout的介绍比较多,requestLayout()方法会触发measure过程和layout过程,不会调用draw过程,也不会重新绘制任何View包括该调用者本身。
onSizeChange(int w, int h, int oldw, int oldh)
onSizeChange是控件的大小发生变化的时候的调用,它的调用轨迹是layout->setFrame->sizeChange->onSizeChange。当控件第一次布局时肯定会被调用到,我们覆写该方法可以获取到控件的大小。所以这个方法通常被用来在里面初始化跟控件大小相关的成员变量。
invalidate
invalidate使用的非常频繁,它会触发View的重新绘制,也就是绘制流程的draw过程,但不会调用测量和布局过程。
postInvalidate
我们都知道Android的UI是单线程模型,只能在主线程更新UI,所以我们只能在主线程调用invalidate,如果想要在子线程更新ui,可以使用handler发送一个msg到主线程,然后在处理msg的时候去调用invalidate。另外,我们可以直接调用postInvalidate去在子线程更新UI,postInvalidate内部实现也是使用handler来发送msg到主线程然后调用invalidate。
|