前言View有很多名字。无论是你熟悉的布局还是控件,都是继承自View。本文部分图片转载自Carson_Ho的文章Mindmapworkflowmeasure其实我们已经通过布局中的第二张图知道了控件大小的计算。height=bottom-topwidth=right-left对于ViewGroup来说,就是容器中子控件的遍历和计算。因为直接继承自View的控件使用wrap_cotent和match_parent来显示一样的效果。我们需要使用MeasureSpec中的getMode()方法来区分和比较当前的模式。模式状态UNSPECIFIED未指定模式,View可以任意大,父容器不限,一般用于系统内部测量AT_MOST最大模式,对应wrap_content,View的大小不大于SpecSize的值EXACTLYExact模式,对应match_parent,View的size是SpecSize的值@OverrideprotectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){super.onMeasure(widthMeasureSpec,heightMeasureSpec);//用来获取设置的模式intwidthMode=MeasureSpec.getMode(widthMeasureSpec);intheightMode=MeasureSpec.getMode(高度/MeasureSpec);/用于获取设置的长度intwidthSize=MeasureSpec.getSize(widthMeasureSpec);intheightSize=MeasureSpec.getSize(heightMeasureSpec);//类似这样的判断后面不再重复//用于判断是否为wrap_content//如果不是则处理,效果会是match_parentif(widthMode==MeasureSpec.AT_MOST&&heightMode==MeasureSpec.AT_MOST){setMeasuredDimension(20,20);}}layout在确定位置的时候,我们有一个很重要的地方——坐标系。Android系统的坐标系与通常的绘图坐标系不同。那么对应的,我们的仓位计算方式自然和我们原来的正好相反。4个顶点的位置由4个值决定:top:子View上边界到容器上边界的距离。left:子View左边框到容器左边框的距离。bottom:子View下边界到容器上边界的距离。right:从子视图的右边界到容器的左边界的距离。所有计算都是相对于它们所在的容器执行的。draw有6个步骤:必要时绘制背景--drawBackground(canvas);保存当前画布层--saveCount=canvas.getSaveCount();绘制View的内容--if(!dirtyOpaque)onDraw(canvas);绘制子视图--dispatchDraw(canvas);必要时,绘制View的褪色边缘,类似阴影效果--canvas.restoreToCount(saveCount);绘制装饰,比如滚动条--onDrawForeground(canvas);关于开发者需要重写的方法一般是onDraw()对应第三步绘制的View的内容。privatePaintpaint=newPaint(Paint.ANTI_ALIAS_FLAG);@OverrideprotectedvoidonDraw(Canvascanvas){super.onDraw(canvas);intwidth=getWidth();intheight=getHeight();//在画布上做这样的事情canvas.drawLine(0,height/2,width,height/2,paint);}入门自定义View在日常项目的布局文件中,我们经常使用xmlns:app="http://schemas.android.com/apk/res-auto"这个tag其实就是用来介绍我们自定义的标签的。1.在res/values中创建attrs
