自定义组合控件的总结

[size=medium]自定义组合控件的总结[/size]
转载请注明出处:[url]http://renyuan-1991.iteye.com/blog/2306381[/url]
第一步:在Values中添加attrs.xml文件,首先搞清楚attts.xml怎么用,下面是一个完整的属性文件。控件的属性其实就为给我们提供某些信息的,我们在区分这个属性的时候不需要去想它能干什么,只要知道它能带来什么就行。比如format为string类型的属性,我们只要知道这个属性能为我们提供string类型的字符串就行,用来干什么依个人喜好而定。

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="GeneralTitle">
<!-- 该属性用来获取String信息 -->
<attr name="name" format="string"/>
<!-- 提供资源文件的引用,如:@drawable/图片ID -->
<attr name="name" format="reference"/>
<!-- 提供颜色值 如:#00FF00-->
<attr name="name" format="color"/>
<!-- 提供一个boolean值 如:true -->
<attr name="name" format="boolean"/>
<!-- 提供一个尺寸值 如:42dip -->
<attr name="name" format="dimension"/>
<!-- 提供一个浮点类型的数值 如:2.2 -->
<attr name="name" format="float"/>
<!-- 提供一个整数类型的数值 如:2 -->
<attr name="name" format="integer"/>
<!-- 提供一个百分比 如:100% -->
<attr name="name" format="fraction"/>
<!-- 枚举值的定义 -->
<attr name="orientation">
<enum name="horizontal" value="0" />
<enum name="vertical" value="1" />
</attr>
<!-- 位或运算(这个从来没用过...) -->
<attr name="windowSoftInputMode">
<flag name = "stateUnspecified" value = "0" />
<flag name = "stateUnchanged" value = "1" />
<flag name = "stateHidden" value = "2" />
<flag name = "stateAlwaysHidden" value = "3" />
<flag name = "stateVisible" value = "4" />
<flag name = "stateAlwaysVisible" value = "5" />
<flag name = "adjustUnspecified" value = "0x00" />
<flag name = "adjustResize" value = "0x10" />
<flag name = "adjustPan" value = "0x20" />
<flag name = "adjustNothing" value = "0x30" />
</attr>
</declare-styleable>
</resources>

在定义Activity的属性时会用到位或运算这个属性,如:
android:windowSoftInputMode = "stateUnspecified | stateUnchanged | stateHidden"

这样做的好处就是减少数据传输,只需要传递一个int值就ok啦。
属性定义时是可以指定多种类型值的,如:
<attr name = "background" format = "reference|color" />

使用:
android:background = "@drawable/图片ID|#00FF00"

第二步:自定义控件的实现
自定义的空间一般都有三个构造函数,这三个构造函数是有一些区别的:
一个参数的构造函数:
在Code中实例化一个View时调用。
两个参数的构造函数:
在xml中定义时调用。
三个参数的构造函数:
一般情况下我们需要显示调用并传入style.默认的Style是指它在当前Application或Activity所用的Theme中的默认Style。

接下来就要往我们这个布局里面添加内容了,比如说这个布局是一个RelativieLaoyut,我们可以通过
LayoutInflater.from(context).inflate(R.layout.imagebtn_with_text, this, true)
这行代码直接从xml中读取一个布局,但是这样会让布局的嵌套又多了一层,因为inflate这个函数的第二个参数就是当前布局,这样就是把xml文件读取的布局添加到我们这个自定义布局中。我们可以通过自己创建控件通过addView()方法生成组合控件。
首先读取自定义的属性,如下:

//读取属性集合
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.GeneralTitle);
//然后从该属性集合中取出自定义属性,如果在xml没有添加对应的属性这里获取的就是null,我们也可以通过这个值来判断是不是要生成对应的控件。
CharSequence title= ta.getText(R.styleable.GeneralTitle_title_text);
int textColor = ta.getColor(R.styleable.GeneralTitle_title_textcolor,0xffffff);
float textSize = ta.getDimension(R.styleable.GeneralTitle_title_textsize,18);
Drawable leftPic = ta.getDrawable(R.styleable.GeneralTitle_title_left_pic);
Drawable rightPic = ta.getDrawable(R.styleable.GeneralTitle_title_right_pic);
float picWidth = ta.getDimension(R.styleable.GeneralTitle_title_pic_width,0);
float title_leftpic_verticalpadding = ta.getDimension(R.styleable.GeneralTitle_title_leftpic_verticalpadding,0);
float title_leftpic_horizontalpadding = ta.getDimension(R.styleable.GeneralTitle_title_leftpic_horizontalpadding,0);
float title_rightpic_verticalpadding = ta.getDimension(R.styleable.GeneralTitle_title_rightpic_verticalpadding,0);
float title_rightpic_horizontalpadding = ta.getDimension(R.styleable.GeneralTitle_title_rightpic_horizontalpadding,0);
float title_leftpic_leftmagin = ta.getDimension(R.styleable.GeneralTitle_title_leftpic_leftmagin,0);
float title_rightpic_rightmagin = ta.getDimension(R.styleable.GeneralTitle_title_rightpic_rightmagin,0);
ta.recycle();//属性拿到后一定要记得释放。
if(null != title) {
//标题
TextView text_title = new TextView(context);
text_title.setText(title);
text_title.setTextColor(textColor);
text_title.setTextSize(TypedValue.COMPLEX_UNIT_PX,textSize);
LayoutParams ttp = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ttp.addRule(CENTER_IN_PARENT);
this.addView(text_title, ttp);
}
if (null != leftPic){
//左边的图片
ImageView imageview_left = new ImageView(context);
imageview_left.setImageDrawable(leftPic);
imageview_left.setPadding((int) title_leftpic_horizontalpadding, (int)title_leftpic_verticalpadding,(int)title_leftpic_horizontalpadding, (int)title_leftpic_verticalpadding);
LayoutParams ilp = new LayoutParams((int) picWidth, ViewGroup.LayoutParams.MATCH_PARENT);
ilp.addRule(ALIGN_PARENT_LEFT);
ilp.addRule(CENTER_VERTICAL);
ilp.setMargins((int) title_leftpic_leftmagin,0,0,0);
imageview_left.setOnClickListener(this);
imageview_left.setTag("investor_title_imageview_left");
this.addView(imageview_left, ilp);
}
if(null != rightPic) {
//右边的图片
ImageView Imageview_right = new ImageView(context);
Imageview_right.setImageDrawable(rightPic);
Imageview_right.setPadding((int)title_rightpic_horizontalpadding,(int)title_rightpic_verticalpadding,(int)title_rightpic_horizontalpadding,(int)title_rightpic_verticalpadding);
LayoutParams irp = new LayoutParams((int)picWidth, ViewGroup.LayoutParams.MATCH_PARENT);
irp.addRule(ALIGN_PARENT_RIGHT);
irp.addRule(CENTER_VERTICAL);
irp.setMargins(0,0, (int) title_rightpic_rightmagin,0);
Imageview_right.setOnClickListener(this);
Imageview_right.setTag("investor_title_imageview_right");
this.addView(Imageview_right, irp);
}

具体的案例详见:GeneralTitle --> http://git.oschina.net/renyuan_1991/MyWidget
获取属性我们也可以利用循环语句,TextView的源码里就是这样写的,如下:

int resourceId = -1;
TypedArray typeArray = context.obtainStyledAttributes(attrs, R.styleable.MyImageView);
ImageView iv = new ImageView(context);
TextView tv = new TextView(context);
int N = typeArray.getIndexCount();
for(int i = 0 ;i<N;i++){
int attr = typeArray.getIndex(i);
switch (attr) {
case R.styleable.MyImageView_Oriental:
resourceId = typeArray.getInt(R.styleable.MyImageView_Oriental, 0);
//
this.setOrientation(resourceId == 1 ? LinearLayout.HORIZONTAL : LinearLayout.VERTICAL);
break;
case R.styleable.MyImageView_Text:
//获取资源,第二个参数是默认值
resourceId = typeArray.getResourceId(R.styleable.MyImageView_Text, 0);
//通过判断资源id是否存在,如果是存在说明在定义的时候定义的是字符串的资源id这里就通过资源id拿到字符,如果不是资源id就直接的到定义时的字符串
tv.setText(resourceId>0? typeArray.getResources().getText(resourceId):typeArray.getString(R.styleable.MyImageView_Text));
break;
case R.styleable.MyImageView_Src:
resourceId = typeArray.getResourceId(R.styleable.MyImageView_Src, 0);
//拿到资源id 如果有就设置给图片,如果没有就直接显示系统的图标
iv.setImageResource(resourceId>0?resourceId:R.drawable.ic_launcher);
break;
}
}
addView(iv);
addView(tv);
typeArray.recycle();//最后要清空属性集合

属性定义如下:

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

<declare-styleable name="MyImageView">
<attr name="Text" format="reference|string"></attr>
<!-- 枚举的没有format 在使用的时候也只能使用这两个属性 在自定义的时候不用指定枚举的名字,获取这个attr的名字就能拿到xml设置的属性 -->
<attr name="Oriental">
<enum name="Horizontal" value="1"></enum>
<enum name="Vertical" value="0"></enum>
</attr>
<attr name="Src" format="reference|integer"></attr>
</declare-styleable>

</resources>

这个例子并没有涉及到view得测量,布局,绘制这个三个必经的流程,如果想看怎么利用这几个方法创建完全自定义的view请看前一篇博客:[url]http://renyuan-1991.iteye.com/blog/2232463[/url]
转载请注明出处:[url]http://renyuan-1991.iteye.com/blog/2306381[/url]
希望爱好编程的小伙伴能加这个群,互相帮助,共同学习。群号: 141877583
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值