Android 自定义控件之日历控件的实现

642 查看

为什么要自定义控件

有时,原生控件不能满足我们对于外观和功能的需求,这时候可以自定义控件来定制外观或功能;有时,原生控件可以通过复杂的编码实现想要的功能,这时候可以自定义控件来提高代码的可复用性。

如何自定义控件

下面我通过我在github上开源的Android-CalendarView项目为例,来介绍一下自定义控件的方法。该项目中自定义的控件类名是CalendarView。这个自定义控件覆盖了一些自定义控件时常需要重写的一些方法。

构造函数

为了支持本控件既能使用xml布局文件声明,也可在java文件中动态创建,实现了三个构造函数。

可以在参数列表最长的第一个方法中写上你的初始化代码,下面两个构造函数调用第一个即可。

那么在构造函数中做了哪些事情呢?

1 读取自定义参数

读取布局文件中可能设置的自定义属性(该日历控件仅自定义了一个mode参数来表示日历的模式)。代码如下。只要在attrs.xml中自定义了属性,就会自动创建一些R.styleable下的变量。

然后附上res目录下values目录下的attrs.xml文件,需要在此文件中声明你自定义控件的自定义参数。

2 初始化关于绘制控件的相关参数

如字体的颜色、尺寸,控件各个部分尺寸。

3 初始化关于逻辑的相关参数

对于日历来说,需要能够判断对应于当前的年月,日历中的每个单元格是否合法,以及若合法,其表示的day的值是多少。未设定年月之前先用当前时间来初始化。实现如下。

其中date[]是一个整型数组,长度为42,因为一个日历最多需要6行来显示(6*7=42),
curStartIndex和curEndIndex决定了date[]数组的合法下标区间,即前者表示该月的第一天在date[]数组的下标,后者表示该月的最后一天在date[]数组的下标。

4 绑定了一个OnTouchListener监听器

监听控件的触摸事件。

onMeasure方法

该方法对控件的宽和高进行测量。CalendarView覆盖了View类的onMeasure()方法,因为某个月的第一天可能是星期一到星期日的任何一个,而且每个月的天数不尽相同,因此日历控件的行数会有多变化,也导致控件的高度会有变化。因此需要根据当前的年月计算控件显示的高度(宽度设为屏幕宽度即可)。实现如下。

其中screenWidth是构造函数中已经获取的屏幕宽度,measureHeight()则是根据年月计算控件所需要的高度。实现如下,已经写了非常详细的注释。

onDraw方法

该方法实现对控件的绘制。其中drawCircle给定圆心和半径绘制圆,drawText是给定一个坐标x,y绘制文字。