概述

Android中View框架的工作机制中,主要有三个过程:

1、View树的测量(measure) Android View框架的measure机制

2、View树的布局(layout)Android View框架的layout机制

3、View树的绘制(draw)Android View框架的draw机制

View框架的工作流程为:测量每个View大小(measure)-->把每个View放置到相应的位置(layout)-->绘制每个View(draw)。

         本文主要讲述三大流程中的draw过程。不清楚measure过程的,可以参考这篇文章 Android View框架的measure机制

                                                                                    不清楚layout过程的,可以参考这篇文章Android View框架的layout机制

这篇文章不讲述graphic模块具体绘制API的使用,只是描述View框架的绘制过程。

带着问题来思考整个draw过程。

1、系统为什么要有draw过程?

View框架在经过了measure过程和layout过程之后,就已经确定了每一个View的尺寸和位置。那么接下来,也是一个重要的过程,就是draw过程,draw过程是用来绘制View的过程,它的作用就是使用graphic框架提供的各种绘制功能,绘制出当前View想要的样子。

2、draw过程都干了点什么事?

View框架中,draw过程主要是绘制View的外观。ViewGroup除了负责绘制自己之外,还需要负责绘制所有的子View。而不含子View的View对象,就负责绘制自己就可以了。

draw过程的主要流程如下:

1、绘制 backgroud(drawBackground)     
       
2、如果需要的话,保存canvas的layer,来准备fading(不是必要的步骤)
       
3、绘制view的content(onDraw方法)
        4、绘制children(dispatchDraw方法)
       
5、如果需要的话,绘制fading edges,然后还原layer(不是必要的步骤)
       
6、绘制装饰器、比如scrollBar(onDrawForeground)

源代码分析

在View的源代码中,提取到了下面一些关于layout过程的信息。

我们知道,整棵View树的根节点是DecorView,它是一个FrameLayout,所以它是一个ViewGroup,所以整棵View树的测量是从一个ViewGroup对象的draw方法开始的。

View:

1、draw

/**

绘制一个View以及他的子View。最好不要覆写该方法,应该覆写onDraw方法来绘制自己。

*/

public void draw(Canvas canvas);

源代码:

这里不给出,有兴趣的读者,可以自行查阅SDK。

伪代码

  1. public void draw(Canvas canvas) {
  2. 1、绘制 backgrouddrawBackground ;
  3. 2、如果需要的话,保存canvaslayer,来准备fading ;
  4. 3、绘制viewcontentonDraw方法);
  5. 4、绘制childrendispatchDraw方法);
  6. 5、如果需要的话,绘制fading edges,然后还原layer ;
  7. 6、绘制装饰器、比如scrollBaronDrawForeground);
  8. }

2、onDraw

/**

绘制一个View的外观。View的默认实现是空实现,所以这里没有源码给出。

*/

protected void onDraw(Canvas canvas);

ViewGroup:

1、dispatchDraw

/** 绘制子View,View类是空实现,ViewGroup类中有实现 */

protected void dispatchDraw(Canvas canvas);

源代码:

这里不再给出,有兴趣的读者自行查阅SDK。

伪代码:

  1. protected void dispatchDraw(Canvas canvas) {
  2. if (需要绘制布局动画) {
  3. for (遍历子View) {
  4. 绑定布局动画;
  5. }
  6. 启动动画控制,通知动画开始;
  7. }
  8.  
  9. for (遍历子View) {
  10. child.draw();
  11. }
  12. }

动手操作

下面我们自己写一个自定义的ViewGroup,让它内部的每一个子View都垂直排布,并且让每一个子View的左边界都距离上一个子View的左边界一定的距离。然后在整个布局内部绘制一个圆形。大概看起来如下图所示:

实际运行效果如下:

代码如下:

  1. public class VerticalOffsetLayout extends ViewGroup {
  2.  
  3. private static final int OFFSET = 100;
  4. private Paint mPaint;
  5.  
  6. public VerticalOffsetLayout(Context context) {
  7. super(context);
  8. init(context, null, 0);
  9. }
  10.  
  11. public VerticalOffsetLayout(Context context, AttributeSet attrs) {
  12. super(context, attrs);
  13. init(context, attrs, 0);
  14. }
  15.  
  16. public VerticalOffsetLayout(Context context, AttributeSet attrs, int defStyleAttr) {
  17. super(context, attrs, defStyleAttr);
  18. init(context, attrs, defStyleAttr);
  19. }
  20.  
  21. private void init(Context context, AttributeSet attrs, int defStyleAttr) {
  22. mPaint = new Paint(Color.BLUE);
  23. mPaint.setAntiAlias(true);
  24. mPaint.setAlpha(125);
  25. }
  26.  
  27. @Override
  28. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  29. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  30.  
  31. int widthMode = MeasureSpec.getMode(widthMeasureSpec);
  32. int heightMode = MeasureSpec.getMode(heightMeasureSpec);
  33. int widthSize = MeasureSpec.getSize(widthMeasureSpec);
  34. int heightSize = MeasureSpec.getSize(heightMeasureSpec);
  35.  
  36. int width = 0;
  37. int height = 0;
  38.  
  39. int childCount = getChildCount();
  40. for (int i = 0; i < childCount; i++) {
  41. View child = getChildAt(i);
  42. ViewGroup.LayoutParams lp = child.getLayoutParams();
  43. int childWidthSpec = getChildMeasureSpec(widthMeasureSpec, 0, lp.width);
  44. int childHeightSpec = getChildMeasureSpec(heightMeasureSpec, 0, lp.height);
  45. child.measure(childWidthSpec, childHeightSpec);
  46. }
  47.  
  48. switch (widthMode) {
  49. case MeasureSpec.EXACTLY:
  50. width = widthSize;
  51. break;
  52. case MeasureSpec.AT_MOST:
  53. case MeasureSpec.UNSPECIFIED:
  54. for (int i = 0; i < childCount; i++) {
  55. View child = getChildAt(i);
  56. int widthAddOffset = i * OFFSET + child.getMeasuredWidth();
  57. width = Math.max(width, widthAddOffset);
  58. }
  59. break;
  60. default:
  61. break;
  62.  
  63. }
  64.  
  65. switch (heightMode) {
  66. case MeasureSpec.EXACTLY:
  67. height = heightSize;
  68. break;
  69. case MeasureSpec.AT_MOST:
  70. case MeasureSpec.UNSPECIFIED:
  71. for (int i = 0; i < childCount; i++) {
  72. View child = getChildAt(i);
  73. height = height + child.getMeasuredHeight();
  74. }
  75. break;
  76. default:
  77. break;
  78.  
  79. }
  80.  
  81. setMeasuredDimension(width, height);
  82. }
  83.  
  84. @Override
  85. protected void onLayout(boolean changed, int l, int t, int r, int b) {
  86. int left = 0;
  87. int right = 0;
  88. int top = 0;
  89. int bottom = 0;
  90.  
  91. int childCount = getChildCount();
  92.  
  93. for (int i = 0; i < childCount; i++) {
  94. View child = getChildAt(i);
  95. left = i * OFFSET;
  96. right = left + child.getMeasuredWidth();
  97. bottom = top + child.getMeasuredHeight();
  98.  
  99. child.layout(left, top, right, bottom);
  100.  
  101. top += child.getMeasuredHeight();
  102. }
  103. }
  104.  
  105. @Override
  106. protected void onDraw(Canvas canvas) {
  107. super.onDraw(canvas);
  108. int x = getWidth()/2;
  109. int y = getHeight()/2;
  110. canvas.drawCircle(x, y, Math.min(x, y), mPaint);
  111. }
  112. }

Android View框架的draw机制的更多相关文章

  1. Android View框架的measure机制

    概述 Android中View框架的工作机制中,主要有三个过程: 1.View树的測量(measure)Android View框架的measure机制 2.View树的布局(layout) Andr ...

  2. Android View框架的layout机制

    概述 Android中View框架的工作机制中,主要有三个过程: 1.View树的测量(measure) Android View框架的measure机制 2.View树的布局(layout)Andr ...

  3. Android View框架总结(八)ViewGroup事件分发机制

    请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52298780 上篇分析了View的事件分发流程,留了一个问题:如果上 ...

  4. Android View的事件分发机制探索

    概述 Android事件传递机制也是Android系统中比较重要的一块,事件类型有很多种,这里主要讨论TouchEvent的事件在framework层的传递处理机制.因为对于App开发人员来说,理解f ...

  5. Android View框架总结(四)View布局流程之Measure

    View树的measure流程 View的measures时序图 View布局流程之measure measure过程 View的measure过程 ViewGroup的measure过程 Frame ...

  6. Android View框架总结(七)View事件分发机制

    请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52282833 View布局告一段落,从本篇开始View事件相关分析, ...

  7. Android view 的事件分发机制

    1 事件的传递顺序是 Activity -> Window -> 顶层View touch 事件产生后,最先由 activity 的 dispatchTouchEvent 处理 /** * ...

  8. Android View框架总结(二)View焦点

    请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52263256 前言:View框架写到第六篇,发现前面第二篇竟然没有, ...

  9. Android View框架总结(三)View工作原理

    转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52180375 测量/布局/绘制顺序 如何引起View的测量/布局/绘制? Perfor ...

随机推荐

  1. JDK14都要问世了,你还在用JDK8吗

    Java开发工具包(JDK)14已进入发布候选阶段,总体功能基本已确定.计划中的标准Java升级将具有新功能,例如JDK Flight Recorder事件流,模式匹配和开关表达式. JDK 14计划 ...

  2. HTML,Css,JavaScript之间的关系

    简述HTML,Css,JavaScript 网页设计思路是把网页分成三个层次,即:结构层(HTML).表示层(CSS).行为层(Javascript). 1.HTML(超文本标记语言 Hyper Te ...

  3. HDU 1017 直接暴力。

    C - 3 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status ...

  4. 用msi安装MySQL时MySQL Server组件不能安装,或安装失败

    我的环境:       MySQL8.0.15,       win10 错误描述:在安装MySQL时,如果MySQL Server组件提示不能安装,错误提示是:VS 2015没有安装或安装失败.原因 ...

  5. codewars--js--vowels counting+js正则相关知识

    问题描述: Return the number (count) of vowels in the given string. We will consider a, e, i, o, and u as ...

  6. Hadoop搭建record下

    前言 先说一下当前环境:Ubuntu18.04 jdk1.8 Hadoop选用-2.6.0-cdh5.15.1 用户名:supershuai-VirtualBox Hadoop的下载地址:http:/ ...

  7. 关于css背景的一点总结

    background默认背景区域覆盖内容和内边距及边框,分别有以下属性: 1.background-clip(定义背景绘制区域) border-box 背景覆盖边框最外面 padding-box 背景 ...

  8. C# WPF 一个设计界面

    微信公众号:Dotnet9,网站:Dotnet9,问题或建议:请网站留言, 如果对您有所帮助:欢迎赞赏. C# WPF 一个设计界面 今天正月初三,大家在家呆着挺好,不要忘了自我充电. 武汉人民加油, ...

  9. 【ffmpeg 视频下载】使用cmd视频下载

    概述 ffmpeg是什么? FFmpeg是一套可以用来记录.转换数字音频.视频,并能将其转化为流的开源计算机程序.并且,很多视频播放器都是采用他的内核. 安装与使用 安装ffmpeg ffmpeg下载 ...

  10. 《自拍教程19》aapt_apk信息查看工具

    aapt命令行工具介绍 aapt.exe(Linux/Ubuntu/imac操作系统下是未带后缀的aapt), 是android sdk自带的用于打包apk,解析apk的命令行工具软件. aapt.e ...