Android群英传--自定义View详解(一)
来源:互联网 发布:kali linux 路由器 编辑:程序博客网 时间:2024/06/06 15:44
Android中的控件架构 :
概述:
Android中所有的控件都继承自View类,View为最顶层的类,然后在其之下又有ViewGroup和View两个大的分类,ViewGroup作为父控件可以包含多个View控件,并管理其所包含的View控件,通过ViewGroup,整个界面形成了一个树形结构,也就是常说的控件树。
实例:
那么具体到一个Activity中,这些控件树又是怎么体现的呢?通常情况下,我们在Activity中使用setContentView()来设置自己需要的界面,那他是怎么将我们的布局文件转换为视图的呢?其实对于每一个Activity而言,其总的View层次为下边的这张图:
对于我们而言,当我们调用setContentView()时设置的只是ContentView中的内容。在Activity中都包含一个Window对象,而Window的实现类就是PhoneView,在ContentView中所有的View点击事件都会通过WindowManagerService来进行接受,然后通过Activity对象来回调对应的OnClickListener。在代码中,当Activity中的onCreate()方法被调用之后,ActivityManagerService会调用onResume(),这时候系统才会把整个DecorView添加到PhoneWindow中,并让其显示出来。
View的测量和绘制:
之前说的都是关于整个Android中View的框架概述,接下来就是关于View具体怎么绘制到屏幕上。
View的测量:
View的具体测量是在onMeasureSpec()这个方法中完成的。同时Android中也提供给我们用于测量的辅助类MeasureSpec。MeasureSpec类是一个32位的int值,其中高两位为测量的模式,低30位是测量的大小。
View的测量模式:
EXACTLY:精确值模式,当我们为控件定义具体的宽高属性时,或者是沾满父控件时使用该测量模式。
AT_MOST:最大值模式,当控件的宽高属性为warp_content时,控件大小一般由控件中的具体内容决定,这时只要该控件不超过父控件的大小即可。
UNSPECIFIED:该模式不指定View大小的测量模式,通常使用自定义View时才会使用该模式。
在自定义View时需要重写View的onMeasure()方法,他默认是调用了父类中的onMeasure()方法。
而父类中的onMesure()方法则是通过setMeasureDimension(),方法来设置View的尺寸。所以我们可以通过在onMeasure()重新计算View的长和宽,然后将其通过setMeasureDimension()方法来修改控件的尺寸。
在onMeasure()中,我们需要根据测量模式来进行不同的计算:
当测量模式为EXACTLY时,直接使用给定的尺寸值,
当测量模式为UNSPECIFIED时,需要给View一个默认的大小,
当测量模式为AT_MOST时,需要将默认的大小和测量出来的最小值进行比较,取其中较小值作为结果。
/** * 重写测量方法 * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec)); } /** * 默认的View大小 */ public static final int DEFAULT_SIZE = 200; /** * 自定义的测量高度的方法 * @param heightMeasureSpec * @return */ private int measureHeight(int heightMeasureSpec) { return measure(heightMeasureSpec); } /** * 自定义的测量宽度的方法 * @param widthMeasureSpec * @return */ private int measureWidth(int widthMeasureSpec) { return measure(widthMeasureSpec); } /** * 自定义的测量方法 * @param measureSpec * @return */ private int measure(int measureSpec) { //获取测量模式和测量值 int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); //最后的测量值 int size = DEFAULT_SIZE; //根据不同的测量模式,有不同的测量结果 if (specMode == MeasureSpec.EXACTLY) { size = specSize; }else{ size = DEFAULT_SIZE; if (specMode == MeasureSpec.AT_MOST) { size = Math.min(specSize,size); } } return size; }
View的绘制:
在将View测量完之后就需要根据要求进行View的绘制,达到我们需要的效果。
关于绘制的详细讲解可以看之前的文章:
Android群英传–绘图机制与处理技巧(一)
Android群英传–绘图机制与处理技巧(二)
Android群英传–绘图机制与处理技巧(三)
在View中重写onDraw()方法,并在其中进行图像的绘制。
ViewGroup的测量和绘制:
ViewGroup的测量:
ViewGroup的测量和View的测量原理相似,只是需要对子View需要遍历测量。
当ViewGroup设置为warp_content时,需要遍历所有的子View,从而决定自己的大小,同样需要重写ViewGroup的onMeasure()方法。
当ViewGroup设置为其他具体的值时就根据具体的值来设置自己的大小。
注:在ViewGroup测量自身尺寸时,会依次调用子View的onMeasure方法来获取测量结果
ViewGroup的布局:
在测量完成之后就需要将所有的子View放在合适的位置,这时候就会通过View的onLayout()方法来为每个子控件找到合适的位置。在布局时同样是通过遍历调用子View的onLayout()方法,指定具体的显示的位置,从而决定布局位置。
ViewGroup的绘制:
ViewGroup自己的绘制任务并不是很重,若不是为其指定了背景色,其甚至不会调用自身的onDraw()方法,在该步骤中,ViewGroup最重要的方法是dispatchDraw()方法,即通过这个方法来遍历调用子View的绘制方法,从而完成绘制。
这些就是一些关于自定义View之前需要了解的基础知识。
相关链接:
Android群英传–绘图机制与处理技巧(一)
Android群英传–绘图机制与处理技巧(二)
Android群英传–绘图机制与处理技巧(三)
Android群英传–动画机制与技巧(一)
Android群英传–动画机制与技巧(二)
- Android群英传--自定义View详解(一)
- 自定义View(一)(Android群英传)
- 自定义View (Android群英传)
- 自定义view android群英传笔记
- 自定义View(二)(Android群英传)
- 自定义View(三)(Android群英传)
- Android群英传-自定义View、控件
- android群英传之自定义View--对现有控件进行扩展(1)
- Android群英传——第三章自定义View
- 《Android 群英传》读书笔记:自定义 View 之创建复合控件
- 《Android 群英传》读书笔记:自定义 View -- 音频条形图
- 《Android群英传》笔记5——自定义View
- 《Android 群英传》读书笔记:自定义 View -- 弧线展示图
- Android 自定义View(一)
- android-自定义View(一)
- android 自定义view(一)
- Android:自定义View(一)
- Android自定义View(一)
- HDU 3172 Virtual Friends(带权并查集)
- 4个主要的map实现类介绍
- The following classes could not be found: - android.support.v7.internal.widget.ActionBarOverlayLayou
- 算法题的五种解法二——模式匹配法
- C提高——结构体
- Android群英传--自定义View详解(一)
- 业务--报文相关
- ssh 免密码登录
- 1012 incryptography
- OPENCV图像处理基础(五)鼠标事件画个框
- equals和hashcode总结
- C++编程迷宫
- 安装ubuntu14.04
- PHP为什么会被认为是草根语言?