您的位置:首页 > 其它

自定义组合控件

2016-06-04 17:02 281 查看
这种自定义组合控件在什么情况下用呢?或者大家在做项目时候会发现,某些布局会被重复的利用,同一个布局的XML代码块会被重复的复制黏贴多次,这样会造成代码结构混乱不说,代码量也会增大,各种控件都需要在Java代码中被申明和处理相应的逻辑,工作量着实不小,所以,必须要找到一个合理的“偷懒”的方式,开动脑经去怎么简化以上说的不必要的麻烦。下面看一张图,就一个简单的布局,我们就此图来实现一个简单的自定义组合控件。



从上面的图来分析,我们可以看到,这个布局里面是没有“全新”的控件的,用的都是Android系统原生的控件。熟悉Android界面布局的人,肯定觉得这种布局真是小Case,太简单了,分分钟就可以写完。于是下面就是某一个条目的布局代码:

?
可以看到,这种布局确实相当的简单。但是,这时候产品经理告诉你,需求改了,我们需要在这个界面再加一个这样的条目,于是你觉得,小意思,Ctrl+C,Ctrl+V,轻松搞定,然后改一下控件的id,在Java代码中findviewbyid(id),加一段逻辑代码,搞完收工。没想到这时候产品又来了,需求改了,这里需要加10个这样的布局,于是你...诚然,这时候再Ctrl+C,Ctrl+V是不合适的,工作量就显得很大了,即使你不嫌麻烦的话,照样做了,你料不到产品会再来,那个给我删掉几个,那个再加上几个,是不是要疯了。

也许,我们可以相出一个偷懒的方法来呢。通过分析上面的布局,可以发现,布局上每一个子条目是不变的,布局完全一样,唯一在变化的是,红色的TextView上的文本随着CheckBox的状态再改变着,而这种变化,我们是否可以想办法抽取到某个方法中呢,答案是肯定能的。我们可以将这种子条目的布局一次性封装到一个Java类中,每次调用这个控件的时候,事先设定各种属性数据即可,这里涉及到了自定义属性了,关于自定义属性,可以参考我的上一篇博客,Android自定义控件——自定义属性,在这里就不在赘述了。分析一下这个属性集该怎么定义,从上面的图片可以看出,控件上需要设置的内容分别是,上面TextView的标题,还有下面TextView的描述信息,且描述信息是根据CheckBox的状态发生改变的,所以这两种状态(true或false)都需要被定义到属性集里去,于是属性集就有了。

在工程下的res/values目录下,新建attrs.xml文件,定义如下属性集:

?
注意:name="combinationView"的combinationView是自定义控件类的类名

定义好了属性集了,接下来我们就需要定义一个Java类,来渲染这段布局,解析这个属性集,并且对象提供修改控件状态的方法,已达到复用的效果。问题来了,我们定义的这个Java类需要继承哪个类呢?在这里,我们不必考虑View了,因为这里不是全新自定义控件,不需要onMessure和onDraw去测量去画一个视图。那么ViewGroup呢?我们也不必用这个类,因为这里的布局是给定好的,不需要使用onLayout给子控件设置显示的位置。那么,该继承什么呢?我们可以想象一下ViewGroup的子类是不是可以呢?实现自定义控件的除了继承View和ViewGroup之外,还可以直接继承Android已有的控件进行修改,这个用面向对象的思想,应该不难想象吧。由于,该布局文件用的相对布局RelativeLayout,我们想当然可以自定义Java类去继承这个RelativeLayout,RelativeLayout里提供一些参数和方法方便我们去实现子控件的布局。但是,我们这里直接在子控件布局已经写好了,不需要使用RelativeLayout提供的参数和方法来布局了。所以,导致了,即使不去继承RelativeLayout,而改成LinearLayout,FrameLayout...也是可以的,只要这个布局类是ViewGroup的子类就行。以下是这个自定义组合控件的实现代码:

?
代码很简单,首先继承RelativeLayout,复写其构造方法,在构造方法中先渲染布局的视图,然后读取属性集的属性,将默认显示的属性显示到布局上的子控件上即可。另外,还要对外提供一个判断状态的方法isChecked()来判断该控件是否被选中了,提供一个设置状态的方法setChecked(boolean),用来改变状态。PS:为了验证我上面的一段话,读者可以将继承RelativeLayout,改为继承LinearLayout或者继承FrameLayout,运行试试看,也是可以实现的。

下面是引用这个自定义组合控件的方法,首先需要在Activity的布局文件中定义出来:

?
首先在上面定义了四个自定义组合控件,大家可以看到,代码精简多了不是?!需要注意的地方:这里引用了自定义的属性集,所以在布局节点上必须要加上命名空间

?
其中,example是命名空间的名称,是任意取的,但是必须在控件中引用属性的名称一致,不然会报错。后面的一串是标明属性集的路径,前半部分是固定的,最后一个“/”后面的内容必须是工程的包名,否则报错。

下面是Activity里面的业务逻辑代码,没什么好说的

?
好了,关于自定义组合控件就讲完了,非常简单,但是比较常用。以后在项目用到时,想想实现步骤,自定义一种的组合的控件,用起来确实比较方便,比单纯的复制黏贴不仅高大上,而且提高代码的复用性,简化了代码的结构和减少了代码量。

总结步骤:

1、定义自定义控件的布局

2、在res/values下定义attrs.xml文件

3、编写自定义控件类,继承RelativLayout等。实现其构造方法。构造方法中需要完成动态添加布局文件、获取属性值、使用属性值更新控件中内容。

4、在布局文件使用该自定义控件并设置属性值
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: