通过直接继承View来实现自定义View的方法简介

  在设计自定义View时,可以选择直接继承View、直接继承ViewGroup、继承特定View、继承特定ViewGroup等方式。本文通过实现一个在屏幕上绘制矩形的自定义View,介绍通过继承View来实现自定义View的方法。

1. 创建继承View的自定义View

  首先创建BlockView直接继承自View:

2. 配置自定义属性

  添加自定义可以让自定义View更加便于使用。首先在/res/values/下新建attrs.xml文件,内容如下:

【完整代码】

其中 BlockView 是自定义View的名称,为它定义了一个名为 blockColor 属性,格式为 color 。

3. 自定义View的构造器

  自定义属性会通过构造器以 AttributeSet 的形式传递给自定义View,需要在自定义View的构造器中过去自定义属性,并对View进行配置。

这里通过 obtainStyledAttributes() 从构造器参数 attrs 中取出 R.styleable.BlockView 的相关属性,然后读取 R.styleable.BlockView_blockColor 属性并保存到本地。 R.styleable.BlockView_blockColor 对应了在前面定义的 blockColor 属性。

4. 自定义View的测量

  在View本身实现的测量流程中,并没有对当其宽或高设置为wrap_content的情况做处理,wrap_content与match_parent相同。对于直接继承View的自定义View,需要根据自身情况,在测量的时候加入对wrap_content的处理。

这里对宽和高MeasureSpec的Mode进行判断:对于宽和高都是 MeasureSpec.AT_MOST ,即wrap_content的情况,就把宽度和高度都设置为默认值;如果宽或高其中之一为 MeasureSpec.AT_MOST ,就把另外一个设置为默认值。这样就可以在宽或高设置为wrap_content时避免占用多余的空间。

5. 自定义View的绘制

  对于直接继承自View的自定义View,默认实现下padding属性也是无法生效的,需要在绘制时考虑各个padding的值。

这里先获取了四个方向的padding,然后在 drawRect() 时,设置所画矩形的左上角坐标为(paddingLeft, paddingTop),右下角坐标为(paddingLeft + width, paddingTop + height)。

6. 为属性添加getter和setter

  为属性添加getter和setter可以动态地对自定义属性进行设置,对于 blockColor 这个自定义属性,getter比较简单,直接返回即可:

但setter的实现需要额外留意,通常我们希望调用setter之后,set的效果可以立即反应在界面上,比如TextView的 setText() 可以立即将所配置的字符串显示到TextView。这里所要实现的 setBlockColor() 也应能够立即改变BlockView中矩形的颜色。

这里额外调用了 invalidate() 来把整个自定义View无效化,这样之后自定义View的 onDraw() 会被再次调用,使用新的参数重新绘制,使得 setBlockColor() 可以立即改变当前BlockView的颜色。

【完整文件】

7. 添加触摸事件处理

  可以通过重写 onTouchEvent() 来实现自定义View对触摸事件的处理。这里为BlockView添加一个水平滑动的手势操作,可以通过水平滑动改变lockView的透明度。实现方法很简单,只要在onTouchEvent() 中添加对 MotionEvent.ACTION_MOVE 的处理即可。

【完整代码】

当发生 MotionEvent.ACTION_MOVE 时,获取当次事件的水平和垂直位移量 dx 和 dy 。若 Math.abs(dx) >= Math.abs(dy) ,即当前为水平位移,则根据水平位移量修改颜色的alpha通道,改变BlockView的透明度。

8. 自定义View的使用

  自定义View的使用和一般的View相同,在布局文件中直接加入即可:

【完整文件】

这里自定义属性 blockColor 使用了前缀 app ,这需要添加schemas声明:

9. 完整代码

  完整代码可以在这里找到。