Android-View的绘制源码学习总结
##前言
算是第一篇正式的github博文,回顾了一下之前看过的view源码解析,做一个对目前为止View学习小的总结。
我觉得对于源码的解析和学习,把所有流程记下来意义并不是很大,最关键的是:
1.知道基本作用和用法
2.大概了解整个流程和实现方法
3.了解里面可扩展的地方在哪,更灵活地使用
4.整个源码设计和细节有没有什么亮点值得参考和学习
5.源码设计的思路
这也是写这篇文章的目的所在。
##加载布局
####LayoutInflater
http://www.cnblogs.com/qlky/p/5674975.html
- **作用**
LayoutInflater是用来加载布局的,我们最简单的代码:
```
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainlayout);
}
```
中的setContentView就是用LayoutInflater实现的
- **用法**
可以用来动态加载布局
```
LayoutInflater layoutInflater = LayoutInflater.from(this);
View buttonlayout = layoutInflater.inflate(R.layout.button_layout,null);
mainlayout.addView(buttonlayout);
```
- **原理**
inflate是用pull来解析xml格式的,其中调用了createViewFromTag()这个方法,并把节点名和参数传了进去。看到这个方法名,我们就应该能猜到,它是用于根据节点名来创建View对象的。
确实如此,在createViewFromTag()方法的内部又会去调用createView()方法,然后使用反射的方式创建出View的实例并返回。
对于布局子元素会用rinflate()去循环实现。
- **拓展**
从源码可以知道
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)的第三个参数attachToRoot
1. 如果root为null,attachToRoot将失去作用,设置任何值都没有意义。
2. 如果root不为null,attachToRoot设为true,则会给加载的布局文件的指定一个父布局,即root。
3. 如果root不为null,attachToRoot设为false,则会将布局文件最外层的所有layout属性进行设置,当该view被添加到父view当中时,这些layout属性会自动生效。
4. 在不设置attachToRoot参数的情况下,如果root不为null,attachToRoot参数默认为true。
所有控件的layout_width等属性,都要有一个父布局才能生效,因为这是用来设置view在布局中的大小,而不是view的大小,所以叫layout_width,不是width。
而LinearLayout的layout_width有效是因为,在setContentView()方法中,Android会自动在布局文件的最外层再嵌套一个FrameLayout,id为content
所以叫setContentView(),其实这个方法也是用Layoutlnflater()实现的
##视图绘制
http://www.cnblogs.com/qlky/p/5676578.html
http://www.jianshu.com/p/5a71014e7b1b
View的绘制要经过三个过程,measure,layout和draw
####Measure
- **作用**
测量view及其子view的大小
- **原理**
MeasureSpec:由父View的MeasureSpec和子View的LayoutParams通过简单的计算得出一个针对子View的测量要求
计算原理很简单:
如果我们在xml 的layout_width或者layout_height 把值都写死,那么上述的测量完全就不需要了,之所以要上面的这步测量,是因为 match_parent 就是充满父容器,wrap_content 就是自己多大就多大, 我们写代码的时候特别爽,我们编码方便的时候,google就要帮我们计算你match_parent的时候是多大,wrap_content的是多大,这个计算过程,就是计算出来的父View的MeasureSpec不断往子View传递,结合子View的LayoutParams 一起再算出子View的MeasureSpec,然后继续传给子View,不断计算每个View的MeasureSpec,子View有了MeasureSpec才能更测量自己和自己的子View。
几种情况:
1.父view MeasureSpec = exactly 大小确定,子view:
match_parent:EXACTLY
warp_content:AT MOST
确定值
2.父view MeasureSpec = exactly 大小不确定,子view:
match_parent:AT MOST
warp_content:AT MOST
确定值
View的测量主要在onMeasure方法里
对于View默认是测量很简单,大部分情况就是拿计算出来的MeasureSpec的size 当做最终测量的大小。而对于其他的一些View的派生类,如TextView、Button、ImageView等,它们的onMeasure方法系统了都做了重写,不会这么简单直接拿 MeasureSpec 的size来当大小,而去会先去测量字符或者图片的高度等,然后拿到View本身content这个高度(字符高度等),如果MeasureSpec是AT_MOST,而且View本身content的高度不超出MeasureSpec的size,那么可以直接用View本身content的高度(字符高度等),而不是像View.java 直接用MeasureSpec的size做为View的大小。
整个View的Root是DecorView,那么View的绘制是从哪里开始的呢,我们知道每个Activity 均会创建一个 PhoneWindow对象,是Activity和整个View系统交互的接口,每个Window都对应着一个View和一个ViewRootImpl,Window和View通过ViewRootImpl来建立联系,对于Activity来说,ViewRootImpl是连接WindowManager和DecorView的纽带,绘制的入口是由ViewRootImpl的performTraversals方法来发起Measure,Layout,Draw等流程的。
具体流程: DecorView -> ... -> content -> LinearLayout/... -> TextView/...
得到每层的MeasureSpec,最后在底层得到大小。然后再往上得到父view的大小
- **拓展**
对于onMeasure方法的重写
####Layout
- **作用**
确定view在布局中的位置。ViewRoot的performTraversals()方法会在measure结束后继续执行,并调用View的layout()方法来执行此过程,如下所示:
```
host.layout(0, 0, host.mMeasuredWidth, host.mMeasuredHeight);
```
- **原理**
首先会调用setFrame()方法来判断视图的大小是否发生过变化,以确定有没有必要对当前的视图进行重绘,同时还会在这里把传递过来的四个参数分别赋值给mLeft、mTop、mRight和mBottom这几个变量。
接下来会调用onLayout()方法。
View中的onLayout()方法是一个空方法,因为onLayout()过程是为了确定视图在布局中所在的位置,而这个操作应该是由布局来完成的,即父视图决定子视图的显示位置。
ViewGroup中的onLayout()方法是一个抽象方法,子类必须重载onLayout函数,而重载onLayout的目的就是安排其children在父视图的具体位置
- **拓展**
重载onLayout函数
####Draw
- **作用**
绘制view
- **原理**
分为六步,其中第二步和第五步在一般情况下很少用到
第一步:背景绘制
第三步,对View的内容进行绘制
onDraw(canvas) 方法是view用来draw 自己的,具体如何绘制,颜色线条什么样式就需要子View自己去实现,View.java 的onDraw(canvas) 是空实现,ViewGroup 也没有实现,每个View的内容是各不相同的,所以需要由子类去实现具体逻辑。
第四步 对当前View的所有子View进行绘制
dispatchDraw(canvas) 方法是用来绘制子View的,View.java 的dispatchDraw()方法是一个空方法,因为View没有子View,不需要实现dispatchDraw ()方法,ViewGroup就不一样了,它实现了dispatchDraw ()方法,就是遍历子View然后drawChild(),drawChild()方法实际调用的是子View.draw()方法,ViewGroup类已经为我们实现绘制子View的默认过程,这个实现基本能满足大部分需求,所以ViewGroup类的子类(LinearLayout,FrameLayout)也基本没有去重写dispatchDraw方法,我们在实现自定义控件,除非比较特别,不然一般也不需要去重写它
第6步 对View的滚动条进行绘制
- **拓展**
重写onDraw方法
Android-View的绘制源码学习总结的更多相关文章
- [Android FrameWork 6.0源码学习] View的重绘过程之WindowManager的addView方法
博客首页:http://www.cnblogs.com/kezhuang/p/关于Activity的contentView的构建过程,我在我的博客中已经分析过了,不了解的可以去看一下<[Andr ...
- [Android FrameWork 6.0源码学习] View的重绘过程之Draw
View绘制的三部曲,测量,布局,绘画现在我们分析绘画部分测量和布局 在前两篇文章中已经分析过了.不了解的可以去我的博客里找一下 下面进入正题,开始分析调用以及函数原理 private void pe ...
- [Android FrameWork 6.0源码学习] LayoutInflater 类分析
LayoutInflater是用来解析XML布局文件,然后生成对象的ViewTree的工具类.是这个工具类的存在,才能让我们写起Layout来那么省劲. 我们接下来进去刨析,看看里边的奥秘 //调用i ...
- [Android FrameWork 6.0源码学习] ViewGroup的addView函数分析
Android中整个的View的组装是采用组合模式. ViewGroup就相当与树根,各种Layout就相当于枝干,各种子View,就相当于树叶. 至于View类.我们就当它是个种子吧.哈哈! Vie ...
- [Android FrameWork 6.0源码学习] View的重绘过程
View绘制的三部曲, 测量,布局,绘画今天我们分析测量过程 view的测量是从ViewRootImpl发起的,View需要重绘,都是发送请求给ViewRootImpl,然后他组织重绘在重绘的过程中 ...
- [Android FrameWork 6.0源码学习] View的重绘过程之Layout
View绘制的三部曲,测量,布局,绘画现在我们分析布局部分测量部分在上篇文章中已经分析过了.不了解的可以去我的博客里找一下 View的布局和测量一样,都是从ViewRootImpl中发起,ViewRo ...
- [Android FrameWork 6.0源码学习] View的重绘ViewRootImpl的setView方法
博客首页:http://www.cnblogs.com/kezhuang/p/ 本篇文章来分析一下WindowManager的后续工作,也就是ViewRootImpl的setView函数的工作 /i* ...
- [Android FrameWork 6.0源码学习] Window窗口类分析
了解这一章节,需要先了解LayoutInflater这个工具类,我以前分析过:http://www.cnblogs.com/kezhuang/p/6978783.html Window是Activit ...
- [Android阅读代码]android-async-http源码学习一
android-async-http 下载地址 一个比较常用的Http请求库,基于org.apache.http对http操作进行封装. 特点: 1.每一个HTTP请求发生在UI线程之外,Client ...
随机推荐
- 开源 PetaPoco 扩展~一个小型轻巧的ORM~
PetaPoco http://www.toptensoftware.com/petapoco/ |PetaPoco is a tiny, fast, single-file micro-ORM fo ...
- Android开发教程 - 使用Data Binding(五)数据绑定
本系列目录 使用Data Binding(一)介绍 使用Data Binding(二)集成与配置 使用Data Binding(三)在Activity中的使用 使用Data Binding(四)在Fr ...
- Java 泛型通配符
package com.waston; import java.util.*; public class Main { public static void main(String[] args) { ...
- 脱壳系列—— 揭开so section加密的美丽外衣
i春秋作家:HAI_ 0×00 前言 对so的加密,https://bbs.pediy.com/thread-191649.htm大神的帖子里已经很详细的说明了.当然加密不是我们研究的重点,如何搞掉这 ...
- 写vue项目时候 零星的笔记
1,挂载也可以用 .$mount() 2,子组件中通过this.$root拿到实例的数据.截图中是子组件中
- Windows上安装tensorflow 详细教程
原博客转载自:https://www.cnblogs.com/lvsling/p/8672404.html 一, 前言:本次安装tensorflow是基于Python的,安装Python的过程不做说明 ...
- 生成代码的代码 之 POJO生成器 之二 模板实现
在之前的一篇博客中,我们写了利用node.js来生成JAVA的POJO代码的方法.有评论说可以利用模板来做这件事.当时认为模板只能做简单的字符串替换,所以可能无法完成任务.但是,仔细的学习了一个模板 ...
- django views视图函数返回值 return redirect httpresponse总结
django views视图函数返回值 return redirect render httpresponse总结
- mvc大对象json传输报错
public ActionResult GetLargeJsonResult() { return new ContentResult { Content = new JavaScriptSerial ...
- Java总结:字符串详解
更新时间:2018-1-6 21:20:39 更多请查看在线文集:http://android.52fhy.com/java/index.html String 字符串创建 String str1=& ...