自定义 View(一)

1,092 阅读3分钟
原文链接: www.jianshu.com


自定义View
需求场景:当系统默认的view不能满足您的优(qi)美(pa)界面要求时候,自定义view则进入您的视野,来满足您的客制化。
那么我们这节开车,来完成自定义view所需要的步骤。
首先,我们先讲一个画画的概念。
我们要画画,需要哪些东西呢? 画板(canvas)需要吧?要不然你画在哪里,对吧。 画笔(paint)要吧?要不然拿什么画,画笔颜料(paint设置参数)要吧?要不画不出来五彩世界。要画个猫猫狗狗,是不是要勾勒(path)下呢?
描述下来,我们发现几个概念:
1 画布(画板)
2 画笔
3 路径
我们调色,给画笔设置颜色,设置画图效果等等东西,然后我们设置画图的轨迹路径,然后在画笔上画出即可。
逻辑伪代码为:
canvas.draw(paint,path);
基础概念就这些。
然后我们再来讲一下view的整个流程。(下面这些名称只是讲解使用,不要强行对号入座)
onInit->onMeasure->onLayout->onDraw
首先,我们构造了一个view,这个new的动作是系统帮你完成的(xml->code)的过程,然后走入它的构造函数,构造里面调用onInit,onInit完成数据的初始化,比如拿到自定义的属性值,文本信息等等。然后进入onMeasure,这个完成我们view的大小测量,测量完了,我们要对我们的view里面的元素进行onLayout布局 (主要这个是在线性或者相对布局里面,去计算子view的实际位置时候使用),测量完了onDraw将我们的东西画到画布上,此时这个便会反馈到界面上显示出来,完成了一个view的整个流程。
看完我上面的描述,不知道是否清楚了呢?为了使得我们自定义view能够少些思考(少走弯路),我这边专门做了一个baseView,如果你需要自定义view,直接继承它,它会强制让你实现一些接口,具体的接口有:


每个函数都有解释,一目了然。
既然封装完成了,我们就拉出来溜溜它。
1:在项目根节点的build.gradle



引入仓库地址,(现在可以省略这一步,库已经加入默认仓库)。

2:在自己的项目build.gradle



引入开源库

3:自定义个view



继承BaseView ,完成它的所有复写方法。这里说明几个关联的方法:

hasViewCustomLayoutonViewLayout 关联,只有hasViewCustomLayout返回true才走onViewLayout,否则走默认的即可。
hasViewCustomMeasure 和 getViewWidthMeasure getViewHeightMeasure一样,只有hasViewCustomMeasure测量返回true后两个函数才走。
4:自定义一个属性(视情况而定)



values下面新加一个attrs.xml文件,里面新增一个属性:

5:布局文件



加入自定义属性

6:MyView去完成初始化



拿到styleable值,在initAttrs里面完成初始化。在initView函数完成其他变量的初始化。这里我们看下测量代码:我偷懒了,直接返回给过来的值。这个值是父类能给到的最大值。这里mode有三种情况:(跟xml对应关系)

wrap_parent -> MeasureSpec.AT_MOST
match_parent -> MeasureSpec.EXACTLY
具体值 -> MeasureSpec.EXACTLY
我们在getViewWidthMeasure 里面可以直接使用switch语句对mode判断,处理具体值即可。
7该画画了



完成路径 设置 ,画笔设置 ,在画布上画一个路径,再画一个文字。看效果,画了个粗糙版本的爱心。



8代码位置
github.com/luxiaoming/…