原文链接
本文是在“剑萧舞蝶”的“Android中View自定义组合控件的基本编写方法”的基础上进行修正而来的。按照原作者的说发和代码来写自定义控件,结果使用的时候出了不少问题。我之前对于这块完全没有去接触,又看到有人说网上的例子都是大同小异,很多细节也没有说清楚,所以在此记一下。
此处的所谓“自定义”组合控件的意思是,一个整体的控件里面包含了若干个控件,比如本文示例的是一个linearlayout包含了两个textview一个CheckBox,使用的时候,是把它们当做一个控件来使用的,并没有什么高深的意思(小小吐槽一下,鄙人很讨厌别人把简单的一件事情说的复杂化)。
来说一下这个“组合控件”的用处。在需要使用若干个相同的布局的时候,最简单也是最不经济的做法就是复制粘贴,需要使用多少次就粘贴多少次,既增添了代码量也不利于管理。如果这个时候有一个现成的封装好的控件能够使用,并且子控件的属性和功能也是封装好的,能节省很多代码量,方便管理,用起来也很爽。这就是组合控件啦,貌似也有人叫它组合View吧。
组合控件的实现是不难的。自定义一个布局类继承自RelativeLayout或者LinearLayout或者FrameLayout........,如果你是采用渲染的方式来完成这个组合控件的,继承自哪个layout都无所谓,如果你是采用addView方式的话,就得考虑用哪个layout比较合适。到此,如果不使用自定义xml属性的话,那么渲染好布局或者添加好控件之后,再根据需求做事件或者逻辑处理,再在需要用的layout里面用上就可以了。像这样:
那么,我们先来自定义xml属性。首先,在/res/values目录下新建一个attrs.xml文件,内容如下:
三个attribute代表有三个属性,属性名字分别desc_off,desc_on,title,三个属性的内容格式都是string类型。ormat有好几种不同的值:string , integer , dimension , reference , color , enum。当format是enum枚举类型的时候,attr里面这样写:
TypedArray attrArray = context.obtainStyledAttributes(attrs, R.styleable.CombinationView);
String title = attrArray.getString(R.styleable.CombinationView_title);
String desc_on = attrArray.getString(R.styleable.CombinationView_desc_on);
String desc_off = attrArray.getString(R.styleable.CombinationView_desc_off);
title,desc_on,desc_off就是我们拿到的属性的值,这时候可以使用它们了。
tv_title.setText(title);
完整的自定义类代码:
完整的attrs.xml代码:
在Activity里边处理事件:
public class SelfDenideViewActivity extends AppCompatActivity implements View.OnClickListener {
private CombinationView combinationView1, combinationView2, combinationView3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_self_denide_view);
combinationView1 = (CombinationView) findViewById(R.id.view1);
combinationView2 = (CombinationView) findViewById(R.id.view2);
combinationView3 = (CombinationView) findViewById(R.id.view3);
combinationView1.setOnClickListener(this);
combinationView2.setOnClickListener(this);
combinationView3.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.view1:
if (combinationView1.isCehcked()) {
combinationView1.setChecked(false);
} else {
combinationView1.setChecked(true);
}
break;
case R.id.view2:
if (combinationView2.isCehcked()) {
combinationView2.setChecked(false);
} else {
combinationView2.setChecked(true);
}
break;
case R.id.view3:
if (combinationView3.isCehcked()) {
combinationView3.setChecked(false);
} else {
combinationView3.setChecked(true);
}
break;
}
}
}
到这里,例子就完了。
有几个需要注意的地方,一个是在attrs.xml文件 中,declare_styleable的name的名称必须和自定义的View的类名称一致,如果是Android studio,输入之后会有提示出来。
一个是 attr属性,除了指定name之外,format也必须指定。
最后的也是最重点的就是命名空间的问题,我就说说我在Android studio使用的情况,刚开始我使用的是应用的包名,就是在AndroidMenifest里边的包名(补充一个,
有人说此自定义的类必须要在应用包名下,不能在子包名下,本人没去试,有兴趣的宝宝可以试一下),结果Android studio直接报红线,然后根据提示,换成了这样子:
xmlns:example="http://schemas.android.com/apk/res-auto"
就好了。