Android - View绘图原理总结

原文地址:http://blog.csdn.net/xu_fu/article/details/7829721

Android系统的视图结构的设计也采用了组合模式,即View作为所有图形的基类,Viewgroup对View继承扩展为视图容器类,由此就得到了视图部分的基本结构--树形结构

View定义了绘图的基本操作

基本操作由三个函数完成:measure()、layout()、draw(),其内部又分别包含了onMeasure()、onLayout()、onDraw()三个子方法。具体操作如下:

1、measure操作

measure操作主要用于计算视图的大小,即视图的宽度和长度。在view中定义为final类型,要求子类不能修改。measure()函数中又会调用下面的函数:

(1)onMeasure(),视图大小的将在这里最终确定,也就是说measure只是对onMeasure的一个包装,子类可以覆写onMeasure()方法实现自己的计算视图大小的方式,并通过setMeasuredDimension(width, height)保存计算结果。

2、layout操作

layout操作用于设置视图在屏幕中显示的位置。在view中定义为final类型,要求子类不能修改。layout()函数中有两个基本操作:

(1)setFrame(l,t,r,b),l,t,r,b即子视图在父视图中的具体位置,该函数用于将这些参数保存起来;

(2)onLayout(),在View中这个函数什么都不会做,提供该函数主要是为viewGroup类型布局子视图用的;

3、draw操作

draw操作利用前两部得到的参数,将视图显示在屏幕上,到这里也就完成了整个的视图绘制工作。子类也不应该修改该方法,因为其内部定义了绘图的基本操作:

(1)绘制背景;

(2)如果要视图显示渐变框,这里会做一些准备工作;

(3)绘制视图本身,即调用onDraw()函数。在view中onDraw()是个空函数,也就是说具体的视图都要覆写该函数来实现自己的显示(比如TextView在这里实现了绘制文字的过程)。而对于ViewGroup则不需要实现该函数,因为作为容器是“没有内容“的,其包含了多个子view,而子View已经实现了自己的绘制方法,因此只需要告诉子view绘制自己就可以了,也就是下面的dispatchDraw()方法;

(4)绘制子视图,即dispatchDraw()函数。在view中这是个空函数,具体的视图不需要实现该方法,它是专门为容器类准备的,也就是容器类必须实现该方法;

(5)如果需要(应用程序调用了setVerticalFadingEdge或者setHorizontalFadingEdge),开始绘制渐变框;

(6)绘制滚动条;

从上面可以看出自定义View需要最少覆写onMeasure()和onDraw()两个方法。

ViewGroup中的扩展操作:

首先Viewgroup是一个抽象类。

1、对子视图的measure过程

(1)measureChildren(),内部使用一个for循环对子视图进行遍历,分别调用子视图的measure()方法;

(2)measureChild(),为指定的子视图measure,会被 measureChildren调用;

(3)measureChildWithMargins(),为指定子视图考虑了margin和padding的measure;

以上三个方法是ViewGroup提供的3个对子view进行测量的参考方法,设计者需要在实际中首先覆写onMeasure(),之后再对子view进行遍历measure,这时候就可以使用以上三个方法,当然也可以自定义方法进行遍历。

2、对子视图的layout过程

在ViewGroup中onLayout()被定义为abstract类型,也就是具体的容器必须实现此方法来安排子视图的布局位置,实现中主要考虑的是视图的大小及视图间的相对位置关系,如gravity、layout_gravity。

3、对子视图的draw过程

(1)dispatchDraw(),该方法用于对子视图进行遍历然后分别让子视图分别draw,方法内部会首先处理布局动画(也就是说布局动画是在这里处理的),如果有布局动画则会为每个子视图产生一个绘制时间,之后再有一个for循环对子视图进行遍历,来调用子视图的draw方法(实际为下边的drawChild());

(2)drawChild(),该方法用于具体调用子视图的draw方法,内部首先会处理视图动画(也就是说视图动画是在这里处理的),之后调用子视图的draw()。

从上面分析可以看出自定义viewGroup的时候需要最少覆写onMeasure()和onLayout()方法,其中onMeasure方法中可以直接调用measureChildren等已有的方法,而onLayout方法就需要设计者进行完整的定义;一般不需要覆写以dispatchDraw()和drawChild()这两个方法,因为上面两个方法已经完成了基本的事情。但是可以通过覆写在该基础之上做一些特殊的效果,比如

[java] view plaincopyprint?

  1. @Override
  2. protected void dispatchDraw(Canvas canvas) {
  3. // TODO Auto-generated method stub
  4. //
  5. //可以在这里先做一些处理,包括对传入的canvas
  6. //
  7. super.dispatchDraw(canvas);         //这里会调用drawChild绘制子视图
  8. //
  9. //所有子视图都绘制完成后这里还可以做一些处理,比如绘制阴影什么的
  10. //
  11. }

其他

从以上分析可以看出View树的绘制是一个递归的过程,从ViewGroup一直向下遍历,直到所有的子view都完成绘制,那这一切的源头在什么地方(是谁最发起measure、layout和draw的)?当然就是在View树的源头了——ViewRoot!,ViewRoot中包含了窗口的总容器DecorView,ViewRoot中的performTraversal()方法会依次调用decorView的measure、layout、draw方法,从而完成view树的绘制。

invalidate()方法

invalidate()方法会导致View树的重新绘制,而且view中的状态标志mPrivateFlags中有一个关于当前视图是否需要重绘的标志位DRAWN,也就是说只有标志位DRAWN置位的视图才需要进行重绘。当视图调用invalidate()方法时,首先会将当前视图的DRAWN标志置位,之后有一个循环调用parent.invalidateChildinParent(),这样会导致从当前视图依次向上遍历直到根视图ViewRoot,这个过程会将需要重绘的视图标记DRAWN置位,之后ViewRoot调用performTraversals()方法,完成视图的绘制过程。

Android - View绘图原理总结

时间: 2024-10-21 06:50:14

Android - View绘图原理总结的相关文章

Android自定义View绘图实现拖影动画

前几天在"Android绘图之渐隐动画"一文中通过画线实现了渐隐动画,但里面有个问题,画笔较粗(大于1)时线段之间会有裂隙,我又改进了一下.这次效果好多了. 先看效果吧: 然后我们来说说基本的做法: 根据画笔宽度,计算每一条线段两个顶点对应的四个点,四点连线,包围线段,形成一个路径. 后一条线段的路径的前两个点,取(等于)前一条线段的后两点,这样就衔接起来了. 把Path的Style修改为FILL,效果是这样的: 可以看到一个个四边形,连成了路径. 好啦,现在说说怎样根据两点计算出包围

Android View 的事件分发原理解析

作为一名 Android 开发者,每天接触最多的就是 View 了.Android View 虽然不是四大组件,但其并不比四大组件的地位低.而 View 的核心知识点事件分发机制则是不少刚入门同学的拦路虎,也是面试过程中基本上都会问的.理解 View 的事件能够让你写出更好自定义 View 以及解决滑动冲突. 1. View 事件认识 1.1 MotionEvent 事件 当你用手指轻触屏幕,这个过程在 Android 中主要可以分为以下三个过程: ACTION_DOWN:手指刚接触屏幕,按下去

深入理解Android View(转)

做android其实也有一段时间了,我们每个人都会碰到一些这样或那样的问题,碰到问题了就拼命百度,可是发现,我们解决问题的能力并没有提升很多,所以我才有想总结一下我项目中所用过的相关知识,并了解一下Android源代码中是如何定义这些属性的,如何去实现的.以后再碰到类似的问题,我该如何实现.本人也不常写博客,希望各位博友能指点,分享,并提出博客中不正确的地方,共勉!    首先我发一份我做的关于Android View深入实现的的XMind的思维导图,可以帮助我一起整理思路,若是博友有什么想到的

Android View系统分析之二View与ViewGroup

目录 在Android View系统分析之从setContentView说开来(一)一文中,我们从setContentView开始阐述了Android中的视图层次,从设置内容布局到整个视图层次的建立的过程.并且对View和ViewGroup的关系进行了简单的介绍,今天我们继续来深入的了解Android中的View和ViewGroup. ViewGroup与View的关系 我们在定义一个布局时,在它的顶层通常都是使用LinearLayout或者RelativeLayout等组件来包装一些子控件,例

深入理解Android View(1)

做android其实也有一段时间了,我们每个人都会碰到一些这样或那样的问题,碰到问题了就拼命百度,可是发现,我们解决问题的能力并没有提升很多,所以我才有想总结一下我项目中所用过的相关知识,并了解一下Android源代码中是如何定义这些属性的,如何去实现的.以后再碰到类似的问题,我该如何实现.本人也不常写博客,希望各位博友能指点,分享,并提出博客中不正确的地方,共勉! 首先我发一份我做的关于Android View深入实现的的XMind的思维导图,可以帮助我一起整理思路,若是博友有什么想到的地方可

Android热修复原理普及

Android热修复原理普及 这段时间比较难闲,就抽空研究一下Android热修复的原理.自从Android热修复这项技术出现之后,随之而现的是多种热修复方案的出现.前两天又看到一篇文章分析了几种热修复方案的比较. 原文地址是:[Android热修复] 技术方案的选型与验证 看完这篇文章,有点汗颜.有这么多的热修复方案,并且他们之间的实现原理也不一样,各有优缺点. 然后在尼古拉斯_赵四的博客中看到几篇关于热修复的文章,对着这几篇文章撸了一番.大概的了解了热修复一种原理,其思路和QQ空间提出的安卓

Android SurfaceView 绘图覆盖刷新及脏矩形刷新方法

http://www.cnblogs.com/SkyD/archive/2010/11/08/1871423.html Android SurfaceView 绘图覆盖刷新及脏矩形刷新方法 SurfaceView在Android中用作游戏开发是最适宜的,本文就将演示游戏开发中常用的两种绘图刷新策略在SurfaceView中的实现方法. 首先我们来看一下本例需要用到的两个素材图片: bj.jpg就是一个渐变图,用作背景. question.png是一个半透明的图像,我们希望将它放在上面,围绕其圆心

Android view 的事件分发机制

1 事件的传递顺序是 Activity -> Window -> 顶层View touch 事件产生后,最先由 activity 的 dispatchTouchEvent 处理 /** * Called to process touch screen events. You can override this to * intercept all touch screen events before they are dispatched to the * window. Be sure to

从零开始学android<android基本绘图.四十六.>

在一般的图形绘制中用户往往只需要覆写onDraw()方法即可,可是如果要想真正的完成绘图的操作,还需要掌握四个核心的操作类: android.graphics.Bitmap:主要表示的是一个图片的存储空间,所包含的图片可以来自于文件或由程序创建: android.graphics.Paint:主要的绘图工具类,可以指定绘图的样式: android.graphics.Canvas:是一个操作绘图以及Bitmap的平台,相当于提供了一个画板的功能,在onDraw()方法的参数中也定义了此类型的参数,