Android自定义xml属性,自定义(组合)控件

来源:互联网 发布:霍山县淘宝农村产业园 编辑:程序博客网 时间:2024/06/04 18:48

原文链接

  本文是在“剑萧舞蝶”的“Android中View自定义组合控件的基本编写方法”的基础上进行修正而来的。按照原作者的说发和代码来写自定义控件,结果使用的时候出了不少问题。我之前对于这块完全没有去接触,又看到有人说网上的例子都是大同小异,很多细节也没有说清楚,所以在此记一下。

此处的所谓“自定义”组合控件的意思是,一个整体的控件里面包含了若干个控件,比如本文示例的是一个linearlayout包含了两个textview一个CheckBox,使用的时候,是把它们当做一个控件来使用的,并没有什么高深的意思(小小吐槽一下,鄙人很讨厌别人把简单的一件事情说的复杂化)。

来说一下这个“组合控件”的用处。在需要使用若干个相同的布局的时候,最简单也是最不经济的做法就是复制粘贴,需要使用多少次就粘贴多少次,既增添了代码量也不利于管理。如果这个时候有一个现成的封装好的控件能够使用,并且子控件的属性和功能也是封装好的,能节省很多代码量,方便管理,用起来也很爽。这就是组合控件啦,貌似也有人叫它组合View吧。

组合控件的实现是不难的。自定义一个布局类继承自RelativeLayout或者LinearLayout或者FrameLayout........,如果你是采用渲染的方式来完成这个组合控件的,继承自哪个layout都无所谓,如果你是采用addView方式的话,就得考虑用哪个layout比较合适。到此,如果不使用自定义xml属性的话,那么渲染好布局或者添加好控件之后,再根据需求做事件或者逻辑处理,再在需要用的layout里面用上就可以了。像这样:

<com.example.administrator.mmpapplication.CombinationView            android:id="@+id/view1"            android:layout_width="match_parent"            android:layout_height="wrap_content"          ></com.example.administrator.mmpapplication.CombinationView>



想看自定义xml属性或者渲染方式的宝宝请往下,继续阅读。

那么,我们先来自定义xml属性。首先,在/res/values目录下新建一个attrs.xml文件,内容如下:

<?xml version="1.0" encoding="utf-8"?><resources>    <!--此处的name必须和自定义View的类名一致-->    <declare-styleable name="CombinationView">        <attr name="desc_off" format="string"></attr>        <attr name="title" format="string"></attr>        <attr name="desc_on" format="string"></attr>    </declare-styleable></resources>


三个attribute代表有三个属性,属性名字分别desc_off,desc_on,title,三个属性的内容格式都是string类型。ormat有好几种不同的值:string , integer , dimension , reference , color , enum。当format是enum枚举类型的时候,attr里面这样写:

<attr name="tEnum">     <enum name="hello" value="-1"/>     <enum name="kitty" value="-2"/> </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);

 完整的自定义类代码:

public class CombinationView extends RelativeLayout { private String TAG = "CombinationView"; private TextView tv_title, tv_desc; private CheckBox cb_status; private String title, desc_on, desc_off; public CombinationView(Context context, AttributeSet attrs) { super(context, attrs);//使用渲染的方式加载布局 View view = View.inflate(context, R.layout.layout_combinationview, this); tv_title = (TextView) view.findViewById(R.id.tv_title); tv_desc = (TextView) view.findViewById(R.id.tv_desc); cb_status = (CheckBox) view.findViewById(R.id.cb_status); TypedArray attrArray = context.obtainStyledAttributes(attrs, R.styleable.CombinationView); title = attrArray.getString(R.styleable.CombinationView_title); desc_on = attrArray.getString(R.styleable.CombinationView_desc_on); desc_off = attrArray.getString(R.styleable.CombinationView_desc_off); Log.e(TAG, "----->title:" + title + " desc_on:" + desc_on + " desc_off:" + desc_off); if (null != title) { tv_title.setText(title); } if (null != desc_off) { tv_desc.setText(desc_off); } } public boolean isCehcked() { return cb_status.isChecked(); } public void setChecked(boolean isChecked) { cb_status.setChecked(isChecked); if (isChecked) { tv_desc.setText(desc_on); } else { tv_desc.setText(desc_off); } }}
完整的attrs.xml代码:

<?xml version="1.0" encoding="utf-8"?><resources> <!--此处的name必须和自定义View的类名一致--> <declare-styleable name="CombinationView"> <attr name="desc_off" format="string"></attr> <attr name="title" format="string"></attr> <attr name="desc_on" format="string"></attr> </declare-styleable></resources>在Activity的布局里边使用自定义控件:<com.example.administrator.mmpapplication.CombinationView android:id="@+id/view1" android:layout_width="match_parent" android:layout_height="wrap_content" example:title="title 1" example:desc_off="unselect 1" example:desc_on="select 1" ></com.example.administrator.mmpapplication.CombinationView>




在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"就好了。


                                             
0 0
原创粉丝点击