本章目录
- Part One:自定义View概述
- Part Two:构造方法
- Part Three:构造方法的写法
Part One:自定义View概述
自定义View可以说是Android里最易学难精的知识点之一,它的入门非常的简单,实现几个固定方法即可,几十行代码就可以画出一个简单的图形。
但是,要想打包票说自己精通自定义View,是非常非常难以做到的事情,因为这里面不仅仅需要处理各种复杂的逻辑,还会涉及到大量的数学算法。
老实说,我也在学习的路上,这里只是给大家抛砖引玉一下。
好了,闲话不多说,自定义View大致上有以下三种应用情况:
- 在现有的控件上,做些个性化的处理(继承自ImageView等 )
- 现有的控件不满足于我们的需求,需要自己去创造(继承自View)
- 讲几个控件组合到一起,新生成一个(继承自ViewGroup)
而继承自现有控件和继承自View的应用方式差不太多,我们用一个画圆的案例把这两种情况需要掌握的各个知识点引入。
Part Two:构造方法
新建一个CircleView类,继承自View,提示需要添加构造方法,如下图所示:
其中,四个参数的构造方法是Android5.0以后引入的,所以最低需要SDK21。
当然,这四个构造方法并不需要全部创建出来,大部分情况下,我们只要掌握前两个即可,我们一一来看下它们的应用场景。
- 首先是一个参数的构造方法。
它的应用范围比较小,没有涉及到属性的添加,不能在XML布局文件中使用。在代码中直接new一个自定义View实例的时候,才会调用此构造方法。例如:
其中,参数传入一个context对象即可生成一个实例,类似于我们直接new一个TextView(this);这种方式。 -
接下来我们看2个参数的构造方法。
这种方法适用于我们常用的控件使用方法,即在XML布局文件中调用自定义View的时候,会使用此构造方法,例如:
高度和宽度是在XML文件中必须写的内容,还有路径要写全,包括包名和类名。完成这两步就可以在代码中实例化该控件了。 - 然后是3个参数的构造方法
这里要非常的注意,在xml布局文件中调用自定义View,并且自定义View标签中还有自定义属性时,这里调用的还是第二个构造函数。
因为系统只会默认调用前两个构造方法,而如果我们想使用自定义属性,或者说后两个构造方法,必须在前面两个构造方法里手动调用(例如:在第二个构造方法里用this关键字调用此构造方法)。 -
最后是4个参数的构造方法
应用方式和三个参数的构造方法一样,都是手动调用。
至于四个参数分别是什么,这里先大概说一下,下一篇文章会详细解释
- context:The Context the view is running in, through which it can access the current theme, resources, etc. 也就是上下文对象
- attrs:The attributes of the XML tag that is inflating the view. 一些基础的XML布局使用的属性值集合。
- defStyleAttr:An attribute in the current theme that contains a reference to a style resource that supplies default values for the view. Can be 0 to not look for defaults. 就是theme中包含一个指向style资源的引用。当我们没有给自定义View设置属性时,就会调用这些默认的值,如果传入0表示不调用该默认值。
- defStyleRes:A resource identifier of a style resource that supplies default values for the view, used only if defStyleAttr is 0 or can not be found in the theme. Can be 0 to not look for defaults. 它的性质和defStyleAttr差不多,但是只有defStyleAttr设置为0或者在当前的theme中没有找到相关属性时,才会去读取该属性,那么很明显优先级是defStyleAttr更高。
Part Three:构造方法的写法
我们常用的构造方法的写法有两种
-
第一种,使用this关键字方式,逐级调用,最终调用四个参数的构造方法:
它的使用方式和官方的控件的构造方法是一样的,我们可以看看官方Button是怎么设计的。
这里官方填写了defStyleAttr这个参数,所以说一般我们继承自View,想要传入参数的时候,使用这种构造方法即可。
但是,如果如果继承自已有的控件,比如Button时,这种构造方法的写法会覆盖掉父类一些默认设置的style。此时,我们最好使用第二种写法。 -
第二种,把初始化的内容封装到一个方法里,给各个构造方法调用:
当然了,并不是说我们必须使用第二种方式去处理继承自已有控件的状况。这么做只是因为可以节省一些工作量,毕竟我们只是在原有的基础上,做一些微调。
官方的控件处理这种状况,依然是使用第一种方式,比如EditText就是继承自TextView,官方把defStyleAttr重新定义了一遍。这里我看不到源码,猜测这两个style有很大概率是有一些继承关系在里面的。相对来说,工作量比较大,改动也比较大。
而如果不需要defStyleAttr时,这两种写法是没有区别的,任意选用即可。
暂时先写到这,下一节会继续写写自定义View的onDraw方法和自定义属性。