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

原文链接

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

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

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

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





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

那么,我们先来自定义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);

 
  
 
  
 
  
 完整的自定义类代码:

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代码:

在Activity的布局里边使用自定义控件:
 
  



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


 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
 

你可能感兴趣的:(Android)