Android App开发过程中,很多时候会遇到系统框架中提供的控件无法满足我们产品的设计需求,那么这时候我们可以选择先Google下有没有比较成熟的开源项目可以让我们用,或者Github上面的项目也非常丰富,能够满足我们绝不多数的开发需求,但是在使用这些炫酷的第三方控件时,需要我们掌控里面实现的细节,所以就滋生了今天“关于android开发中自定义view的探索”
粗体是我个人的疑问,下面小字部分是结合查阅资料以及实际操作的归纳理解。
什么是View?
Android所有的控件都是View或者View的子类,它其实表示的就是屏幕上的一块矩形区域,用一个Rect来表示,left,top表示View相对于它的parent View的起点,width,height表示View自己的宽高,通过这4个字段就能确定View在屏幕上的位置,确定位置后就可以开始绘制View的内容了。
View绘制过程是怎样的?
View的绘制可以分为下面三个过程:
- Measure
View会先做一次测量,算出自己需要占用多大的面积。View的Measure过程给我们暴露了一个接口onMeasure,方法的定义是这样的,protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {}
View类已经提供了一个基本的onMeasure实现,
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); } public static int getDefaultSize(int size, int measureSpec) { int result = size; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); switch (specMode) { case MeasureSpec.UNSPECIFIED: result = size; break; case MeasureSpec.AT_MOST: case MeasureSpec.EXACTLY: result = specSize; break; } return result; }
其中invoke了setMeasuredDimension()方法,设置了measure过程中View的宽高,getSuggestedMinimumWidth()返回View的最小Width,Height也有对应的方法。我们可以重写onMeasure来重新定义View的宽高。
- Layout
Layout过程对于View类非常简单,同样View给我们暴露了onLayout方法
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
}
因为我们现在讨论的是View,没有子View需要排列,所以这一步不需要做额外的工作。
3. Draw
Draw过程,就是在canvas上画出我们需要的View样式。同样View给我们暴露了onDraw方法
protected void onDraw(Canvas canvas) { }
默认View类的onDraw没有一行代码,但是提供给我们了一张空白的画布,就像一张画卷一样,我们就是画家,能画出什么样的效果,完全取决我们。
在实例中看到的方法
- requestLayout
View重新调用一次layout过程。 - invalidate
View重新调用一次draw过程 - forceLayout
标识View在下一次重绘,需要重新调用layout过程。
布局文件怎么配置?
自定义控件属性,我们都知道View已经有一些基本的属性,比如layout_width,layout_height,background等,我们往往需要定义自己的属性,那么具体可以这么做。
- 1.在values文件夹下,打开attrs.xml,其实这个文件名称可以是任意的,写在这里更规范一点,表示里面放的全是view的属性。
- 2.下面创建了三个属性
<declare-styleable name="rainbowbar"> <attr name="rainbowbar_hspace" format="dimension"></attr> <attr name="rainbowbar_vspace" format="dimension"></attr> <attr name="rainbowbar_color" format="color"></attr> </declare-styleable>