绘图机制
来源:互联网 发布:广电网络招聘 编辑:程序博客网 时间:2024/05/18 01:22
由浅入深的说明Android绘图机制
- Android中每一个组件的绘制过程,都要经过三个阶段:测量、布局、绘制,分别对应着方法
onMeasure
、onLayout
、onDraw
(这三个方法定义于View类中)。当然,这三个方法都是允许组件自己重定义的方法,来实现组件对自己的尺寸进行测量(①有child views时,要分别对子组件调用相关测量方法,比如measureChild
、measureChildWithMargins
等,并根据子组件的dimension来确定自己的尺寸;②最后要调用setMeasuredDimension(measuredWidth, measuredHeight)
方法来保存自己的尺寸信息。)、对自己进行布局(调用onLayout
,如果是container,同样需要对子组件进行布局,调用子组件的layout(int l, int t, int r, int b)
方法,最终同样会执行子组件的onLayout
方法来实现对子组件的布局(布局说白了就是确定自己的绘制位置与大小,即左上右下四个坐标(这样也就提供了大小)),对于容器来说,将其中的具体组件布局好了,也就将其布局好了)以及绘制自己的内容(调用onDraw
方法,使用该方法的参数Canvas进行内容绘制); - 从代码中看,Android的绘图是从ViewRootImpl类的
performTraversals
方法开始的,可以把这个方法视为一个顶层的控制方法,在其中控制整个绘图的流程。具体情况如下所述:
Ⅰ首先,在其中会调用performMeasure
方法,在performMeasure
方法中调用View的measure
方法(View的measure
是final方法,方法原型为:public final void measure(int widthMeasureSpec, int heightMeasureSpec)
,
也就是说不允许子类修改测量的框架,只能够修改真正进行测量工作的onMeasure
方法),进而调用具体组件所实现的onMeasure
方法。
Ⅱ然后,测量结束后会调用performLayout
方法,在performLayout
方法中调用View的layout
方法,该方法原型为:public void layout(int l, int t, int r, int b)
,
在该方法中会调用View的onLayout
方法,对组件进行布局。
在拓展ViewGroup类的时候,对于所重写的onLayout
方法,一般最后一步就是分别调用组件各自的layout
方法来“Place the child.”。
Ⅲ之后,会调用performDraw
方法,通过performDraw -> draw -> drawSoftware
最终会调用View的draw(Canvas)
方法。在draw
方法中会有六步操作,在第三步“draw the content”时会调用onDraw(Canvas)
方法,进行内容的绘制。 - 总结:
如果我们要拓展ViewGroup类实现一个布局,就要在其中重写onMeasure
方法来对布局中的组件进行测量,并在获得其中所有组件的尺寸后计算得到布局的尺寸,然后调用setMeasuredDimension
方法进行设置;之后还需要重写onLayout
方法,在其中调用各个组件的layout
方法,传入计算出的组件坐标位置,实现对组件的布局。
至于绘制,则由具体的组件自己重写onDraw
方法进行实现,在ViewRootImpl类的performTraversals
逻辑中进行控制。 - 附加:
①在测量结束后(调用方法setMeasuredDimension
后),就可以调用getMeasuredWidth
和getMeasuredHeight
来获取视图测量出的宽和高了,在这之前这两个方法返回值均为0;
在布局结束后,就可以调用方法getWidth
和getHeight
来获取视图的宽高了。
以上就是getMeasuredXXX
与getXXX
的区别,由于一般情况下,会根据测量的情况去布局组件,所以这两个方法的返回值是一样的。
②关于MeasureSpec
MeasureSpec由specSize与specMode两部分组成,前者是大小信息,后者是模式信息。包括的模式有:
EXACTLY
表示父视图希望子视图的大小应该是由specSize的值来决定的,系统默认会按照这个规则来设置子视图的大小,开发人员当然也可以按照自己的意愿设置成任意的大小。
AT_MOST
表示子视图最多只能是specSize中指定的大小,开发人员应该尽可能小得去设置这个视图,并且保证不会超过specSize。系统默认会按照这个规则来设置子视图的大小,开发人员当然也可以按照自己的意愿设置成任意的大小。
UNSPECIFIED
表示开发人员可以将视图按照自己的意愿设置成任意的大小,没有任何限制。这种情况比较少见,不太会用到。
MeasureSpec是一个32位的int数,其中的2位用来表示模式,余下30位用来表示size。 - 看
performTraversals
代码时会发现,比如进行布局的时候,代码中所调用的是performLayout
方法,在该方法中所执行的关键操作是host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
当时我想,这一个调用怎么实现对所有组件的布局的呢?还因此在代码中找了好一会儿循环语句,现在我明白了:这个host是个布局对象,调用其layout
会进一步调用其onLayout
方法,在onLayout
方法中实现对所有子组件的遍历布局。同理,测量也是这样的。
1 0
- 绘图机制
- OpenGL 绘图的机制
- java绘图机制
- iOS的绘图机制
- Java绘图机制
- iOS的绘图机制
- Java swing绘图机制
- SurfaceView绘图机制
- SurfaceView绘图机制
- iOS的绘图机制
- android draw绘图机制
- iOS绘图机制1
- iOS绘图机制2
- Android SurfaceView绘图机制
- ios中的绘图机制
- Android View绘图机制
- 绘图机制ColorMatrix
- Android---绘图机制---SurfaceView
- C#界面设计之TabControl控件的使用
- Mybatis最入门---ResultMaps实例篇(一对多查询)
- Qt编程--发现小知识点,析构Object类时,自动析构其子对象
- Android--JNI编程详解
- 宏碁V3-572G-51MR安装CUDA5.5失败
- 绘图机制
- java获取propertites文件
- 动态规划 DP问题
- 关于block使用导致键盘的延时操作
- bzoj 3209: 花神的数论题 数位dp
- Kafka的设计思想、理念
- hibernate里createSQLQuery
- 应用层之E-mail服务及javaMail邮件发送的知识总结
- 桶排序_改进结构体