好纠结,弄了一个下午老是报错如是总结一下安卓自定视图和自定义属性。
(一)自定义属性
在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>
总结:
- 记得自定义调用构造函数的区别
- 不能忘了自定义命名空间的