Android 自定义 attr

好纠结,弄了一个下午老是报错如是总结一下安卓自定视图和自定义属性。

 

(一)自定义属性

  在Values文件下建立一个attrs.xml文件,attr的format可以参考:http://www.cnblogs.com/crashmaker/p/3521310.html

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="nfyh">
        <attr name="title" format="reference"/>
        <attr name="icon" format="reference"/>
        <attr name="border_width" format="dimension"/>
        <attr name="enable_right" format="boolean"/>
        <attr name="selected" format="boolean"/>
    </declare-styleable>

</resources>

 

 

 

(一)自定义视图(View)

 

/**
 * 列表项视图
 * 
 * @author Chenrui
 * 
 */
public class ListItemView extends LinearLayout
{
    
    private TextView        tvTitle;
    private TextView        tvSubTitle;
    private ImageView        imgNext;
    private OnClickListener    listener;
    private Context            context;
    private View            viewBorder;
    private LinearLayout    customerViews;
    private Intent            nextIntent;
    
    public ListItemView(Context context,AttributeSet attrs)
    {
        this(context, attrs, 0); // 使用XML文件布局的时候,不会调用 ListItemView(Context context) 的构造函数,如果有主题的需要调用这个构造函数
    }
    
    public ListItemView(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
        this.context = context;
        LayoutInflater.from(context).inflate(R.layout.view_list_item, this); //初始化布局
        this.tvTitle = (TextView) this
                .findViewById(R.id.tv_view_liset_item_title);
        this.tvSubTitle = (TextView) this
                .findViewById(R.id.tv_view_liset_item_sub_title);
        this.imgNext = (ImageView) this
                .findViewById(R.id.img_view_liset_item_right);
        
        this.viewBorder = findViewById(R.id.view_list_item_border);
        customerViews = (LinearLayout) this
                .findViewById(R.id.viewStub_view_list_item);
        
        initView(attrs, defStyle);
    }
    
    private void initView(AttributeSet attrs, int defStyle)
    {
        if (attrs == null) return; //赋值
        
        TypedArray typeArray = null;
        try
        {
            typeArray = context.obtainStyledAttributes(attrs, R.styleable.nfyh,
                    defStyle, 0); //这里获取自定义属性
            
            int count = typeArray.getIndexCount();
            //试过使用typeArray.getString(R.styleable.nfyh_title);获取不了值,不知道为何??!!
            for (int i = 0; i < count; i++)
            {
                int index = typeArray.getIndex(i); 
                switch (index)
                {
                    case R.styleable.nfyh_title:
                        this.setText(typeArray.getString(index)); break;
                    case R.styleable.nfyh_enable_right:
                        this.setNextEnable(typeArray.getBoolean(index, false));
                        break;
                    case R.styleable.nfyh_selected:
                        if (typeArray.getBoolean(index, false)) this
                                .setSelected();
                        break;
                    case R.styleable.nfyh_icon:
                        this.setIcon(typeArray.getResourceId(index, 0));
                        break;
                    case R.styleable.nfyh_border_width:
                        this.setBorder(typeArray.getDimensionPixelOffset(index,
                                1));
                        break;
                    default:
                        break;
                }
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            typeArray.recycle();//一定要调用回收
        }
    }
    
    @Override
    public void setOnClickListener(View.OnClickListener l)
    {
        super.setOnClickListener(l);
        this.listener = l;
    }
    
    public void setIcon(int id)
    {
        this.tvTitle.setCompoundDrawablesWithIntrinsicBounds(id, 0, 0, 0);
        
    }
    
    public void setText(String text)
    {
        this.tvTitle.setText(text);
    }
    
    public void setSubText(String text)
    {
        this.tvSubTitle.setText(text);
    }
    
    public void setSelected()
    {
        this.tvTitle.setTextColor(context.getResources()
                .getColor(R.color.green));
    }
    
    public void setBorder(int height)
    {
        this.viewBorder.setLayoutParams(new LayoutParams(
                LayoutParams.MATCH_PARENT, height));
        //        this.viewBorder.setBackgroundColor(colorID);
    }
    
    public void setNextEnable(boolean value)
    {
        int visibility = value ? View.VISIBLE : View.GONE;
        this.imgNext.setVisibility(visibility);
    }
    
    public void setCustomerView(View v)
    {
        customerViews.addView(v);
    }
    
    public void removeCustomerViews()
    {
        customerViews.removeAllViews();
    }
    
    public void setNextIntent(Intent intent)
    {
        this.nextIntent = intent;
    }
    
}

 

在布局文件中使用自定义视图,直接使用包名。

<com.yixin.nfyh.cloud.ui.ListItemView style="@style/Widget.Light.IOS.ListItem.Title" 
                nfyh:title="@string/canshuxuanzhe">
            </com.yixin.nfyh.cloud.ui.ListItemView>

 

 

这里很重要的是命名空间,这里的命名空间(xmlns:nfyh)是可以随便命名的,和attrs的name不必对上。

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:nfyh="http://schemas.android.com/apk/res-auto" //注意这里,res-auto也可以是你的包名 xmlns:nfyh="http://schemas.android.com/apk/res/com.yixin.nfyh.cloud"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#eeeded"
    android:orientation="vertical" >
   <com.yixin.nfyh.cloud.ui.ListItemView style="@style/Widget.Light.IOS.ListItem.Title" 
                nfyh:title="@string/canshuxuanzhe">
            </com.yixin.nfyh.cloud.ui.ListItemView>

            <LinearLayout
                android:id="@+id/ll_ui_sign_detail_params_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical" >
            </LinearLayout>

 


.... 此处省略

 

 

 

 style文件

 

 <style name="Widget.Light.IOS.ListItem.Title" parent="@style/match_warp">
        <item name="android:layout_marginBottom">10dp</item>
        <item name="android:layout_marginTop">10dp</item>
        <item name="android:orientation">vertical</item>
    <!-- ...以下自定以属性 -->
<item name="border_width">5dp</item> <item name="icon">@drawable/ic_tile_list</item> <item name="selected">true</item> <item name="enable_right">false</item> </style>

 

 

 总结:

 

  1. 记得自定义调用构造函数的区别
  2. 不能忘了自定义命名空间的

 

 

posted @ 2014-03-20 18:16  rae  阅读(721)  评论(0编辑  收藏  举报