android笔记之自定义组件

今天学习了一下自定义组件,在android的开发中经常会有一个布局文件多次重复使用的情况,google提供了自定义组件的的功能可以让开发这根据自己的情况自己“DIY”。来是怎样实现的呢?

本文基于android studio开发,在eclipse中的自定义组件和android studio中有差异,在这里就不两个都介绍了。

定义一个自定义属性xml文件

在项目中创建一个attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MySettingItemView">
        <attr name="tv_setting_title"
              format="string"></attr>
        <attr name="tv_setting_content"
              format="string"></attr>
</declare-styleable>
</resources>

自定义命名空间

这段代码声明了两个自定义属性,tv_setting_title, ltv_setting_content, 一旦你定义自定义属性,你可以 在布局XML文件使用它们就像内置的属性。唯一的区别是你的自定义属性属于一个不同的名称空间。而不是属于http://schemas.android.com/apk/res/android名称空间,他们属于http://schemas.android.com/apk/res/(你的包名称)。举例来说如何使用属性为 MySettingItemView定义 :在eclipse中要将第二行改为
  xmlns:自定义的命名空间="http://schemas.android.com/apk/res/<span style="color: rgb(37, 37, 37); font-family: 'Microsoft YaHei';font-size:18px; line-height: 19.2px;">(你的包名称)</span>"
在android studio中直接可以将项目包名改为res-auto
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:geowind="http://schemas.android.com/apk/res-auto"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
  

创建一个View类,获取自定义属性数据

本文以自定义LinearLayout为例,其实原理就是和android自带的组件一样,只是两个的命名空间不同

 public MySettingItemView(Context context, AttributeSet attrs) {//attrs为自定义组件的属性
        super(context, attrs);
        mItem = View.inflate(context, R.layout.item_settingceneter,null);//布局中的条目布局
        //获取attrs.xml中stylead中的attr
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.MySettingItemView,
                0, 0);
        initView();
        //将item加到自定义布局中
        addView(mItem);
        try {
           <pre name="code" class="java">  //获取要title的名字
            mTitle=mA.getString(R.styleable.MySettingItemView_tv_setting_title);
            //获取tv_content的内容
            mContent=mA.getString(R.styleable.MySettingItemView_tv_setting_content);
            setTitle(mTitle);
            mContents = mContent.split("-");//将checkbox的内容通过“-”分割成两部分存放在数组中
            setContent(mContents[1]);


} finally { a.recycle();//回收资源 } }<pre name="code" class="html">private void initView() { mTv_title = (TextView) mItem.findViewById(R.id.tv_settingCenter_title); mTv_content = (TextView) mItem.findViewById(R.id.tv_settingCenter_content); mCb_check = (CheckBox) mItem.findViewById(R.id.cb_update); }
 
 

 在自定义组件中使用自定义属性 
 

  <com.geowind.mysafegaurd.MySettingItemView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        geowind:tv_setting_title="更新设置"
        geowind:tv_setting_content="已经开启-已经关闭"/>

    <com.geowind.mysafegaurd.MySettingItemView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        geowind:tv_setting_title="更新设置2"
        geowind:tv_setting_content="已经开启-已经关闭2"/>

    <com.geowind.mysafegaurd.MySettingItemView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        geowind:tv_setting_title="更新设置3"
        geowind:tv_setting_content="已经开启-已经关闭3"/>

    <com.geowind.mysafegaurd.MySettingItemView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        geowind:tv_setting_title="更新设置4"
        geowind:tv_setting_content="已经开启-已经关闭4"/>

如何给自定义组件设置点击事件

自定义组件的点击事件可以直接用组件父类原有的,但是这样做只能写一个监听事件,也就是说当要使用这一个自定义组件时,所用的点击事件都是一样的,这样做就将代码写死了,解决这一点就需要自定义组件的监听事件

1.将LinearLayout的clickable属性改为true,Linealayout的clickable默认是为false的

2.暴露自定义view类的属性接口,要想访问自定义组件的成员属性,必须写一个方法设置

 private void setTitle(String title){
        mTv_title.setText(title);
        invalidate();
        requestLayout();
    }
    private void  setContent(String content){
        mTv_content.setText(content);
        invalidate();
        requestLayout();
    }<pre name="code" class="java"> //为外界提供访问cb_check的接口
    public boolean isChecked(){
        return mCb_check.isChecked();
    }
    public  void  setChecked(boolean ischecked){
        if(ischecked){
            setContent(mContents[0]);
            mTv_content.setTextColor(Color.GREEN);
        }else {
            setContent(mContents[1]);
            mTv_content.setTextColor(Color.RED);
        }
        mCb_check.setChecked(ischecked);
    }

 3.自定义点击事件 
 

 public void setItemClickListener(OnClickListener l){
        mItem.setOnClickListener(l);
    }

4.调用自定义组件的点击事件

到这里就可以去调用我们自己定义的点击事件了

  setContentView(R.layout.settingcenter);
        mMv_settingUpdate = (MySettingItemView) findViewById(R.id.mv_setting_update);

 mMv_settingUpdate.setItemClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
               if(mMv_settingUpdate.isChecked()){
                   SpTools.putBoolean(getApplicationContext(),MyConstant.AUTOUPDATE,false);
                   mMv_settingUpdate.setChecked(!mMv_settingUpdate.isChecked());
               }else {
                   SpTools.putBoolean(getApplicationContext(), MyConstant.AUTOUPDATE,true);
                   mMv_settingUpdate.setChecked(!mMv_settingUpdate.isChecked());
               }
            }
        });




发布了38 篇原创文章 · 获赞 6 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/coderlady/article/details/51878800