首页 > 其他 > 详细

自定义控件(View的绘制流程源码解析)

时间:2015-10-27 19:32:20      阅读:394      评论:0      收藏:0      [点我收藏+]
一直以来我们都是在用Andriod自带的控件,比如TextView,ImageView等来构建我们的应用,有的时候并不能满足我们的需要,接下来就来研究一下如何自定义我们自己的控件,当然自己造新的轮子,自然先要搞懂系统自带的轮子的实现原理,下面将从源码的角度深入分析view的绘制流程,进而来分析一下如何自定义新的控件:
下面首先从源码的角度来分析一下view的绘制流程:
先看一下view树的结构图:
技术分享
技术分享
可以看到android中任何一个布局或控件都是直接或间接继承于view实现的,对于我们后面要自定义的控件自然也不例外,所以想要自定义控件首先必须得先搞明白android自带的view布局和控件到底是如何绘制并显示到屏幕上的。
1、既然要把view绘制到屏幕上,那自然首先要搞清楚绘制是从哪开始的?
整个View树的绘图流程是在ViewRootImpl类的performTraversals()方法开始的,这个方法很长,我们抽取主要的代码逻辑展示出来:
1 childWidthMeasureSpec = getRootMeasureSpec(baseSize, lp.width);
2                 childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
3                 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
 1 /**
 2      * Figures out the measure spec for the root view in a window based on it‘s
 3      * layout params.
 4      *
 5      * @param windowSize
 6      *            The available width or height of the window
 7      *
 8      * @param rootDimension
 9      *            The layout params for one dimension (width or height) of the
10      *            window.
11      *
12      * @return The measure spec to use to measure the root view.
13      */
14     private static int getRootMeasureSpec(int windowSize, int rootDimension) {
15         int measureSpec;
16         switch (rootDimension) {
17 
18         case ViewGroup.LayoutParams.MATCH_PARENT:
19             // Window can‘t resize. Force root view to be windowSize.
20             measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY);
21             break;
22         case ViewGroup.LayoutParams.WRAP_CONTENT:
23             // Window can resize. Set max size for root view.
24             measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST);
25             break;
26         default:
27             // Window wants to be an exact size. Force root view to be that size.
28             measureSpec = MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY);
29             break;
30         }
31         return measureSpec;
32     }
可以看到该方法内部会调用view的measure方法,getRootMeasureSpec方法中传入了两个参数,其中lp.width和lp.height在创建ViewGroup实例时等于MATCH_PARENT,也就是说在ViewGroup实例创建的时候就被赋值了
那这里lp是什么呢?    WindowManager.LayoutParams lp = mWindowAttributes;  (注: WindowManager.LayoutParams 是 WindowManager 接口的嵌套类;它继承于 ViewGroup.LayoutParams; 它用于向WindowManager描述Window的管理策略。)实际上lp即为屏幕参数,从getRootMeasureSpec方法的实现中可以看出无论rootDimension是MATCH_PARENT或WRAP_CONTENT,最后都会强制将root view转换为全屏的,查看上面的case语句分支可以知道通过调用makeMeasureSpec方法根据传入的specSize:windowSize和specMode参数对MeasureSpec重新封装,尺寸全部为windowSize,所以根视图总是全屏的
至此我们也便明白了最外层根视图的widthMeasureSpec和heightMeasureSpec是从哪里来的了。
接下来就是对view的绘制流程,下面就是绘制流程图:
技术分享
 
 
技术分享

自定义控件(View的绘制流程源码解析)

原文:http://www.cnblogs.com/CoolRandy/p/4915072.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!