您的位置:首页 > 移动开发 > Android开发

野人学Android第二弹——自定义控件的分析与实例

2015-11-17 11:18 537 查看
在学会Android基础的控件之后,有没有想自己开发一个控件呢?随着各种需求的提出,基础的控件已经不能满足Android的开发,幸好可以自定义控件,那么这一篇博文,就跟大家聊聊自定义控件。
想要跑,先学走。在自定义之前,让我们整理下Android原装控件是怎么运行的:

1.xml文件中会声明一个控件,然后就是各种属性;
2.JAVA文件中会加载这个xml;
3.如果有监听事件,控件会在java中初始化,然后绑定相应的监听事件;
根据上面的信息,可以推测,有相关的类获取xml中的属性,并且将这些属性与相应的控件绑定在一起,并且会给这些控件绑定相应的监听事件接口。想来想去,找Button开刀,追溯到View这个类存在大量的业务代码。找了半天,找到下面一些代码,而这些代码验证了我的推测。



关于参数的解释,不懂的可以自行翻译,在这里就不多说了。要强调的是,attrs这个参数是xml中对应的属性,也就是推测1中的控件属性。既然有了控件属性,那么怎么从xml中转换成java的代码呢。这里要说下TypeArray这个类型以及context.obtainStyledAttributes()这个方法。就是将xml中的属性转换成数组类型。



如上图所示:

第一步,在循环中获取数组中的属性值;
第二步,按照条件进行选择,其中case后面的条件就是xml中具体的属性名称,只不过最后一个“.”后面的构成规则有点讲究,这个在后面的实例中会讲解;
第三步,就是将指定的属性值赋值给对应的参数。

分析到这里,其实已经完成一大步了。不同的控件,赋值的方法不一样。并且本博文中讲到的自定义控件,也是建立在基础控件的基础上的,所以接下来就要用到基础控件的属性设定方法。如果自定义的控件没有监听事件,分析到这里也差不多了。既然对自定义控件的分析完毕,那么就来具体实现一下吧。
网络上有很多教程,我大概总结下了,有这么几步:

1.在values文件夹中新建“atts.xml”文件,定义控件的属性;
2.新建自定义控件的class文件,继承RelativeLayout类,按照上面的思路,获取xml文件中的属性值,然后新建基础控件,并且将属性值赋予这些控件;
3.如果有监听事件,那么写一个监听接口,最后添加在相应的监听事件中,这样从外界就可以添加事件了。
如果不理解这几步,那么来看看具体的代码吧。
第一步,新建atts.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Topbar">
<attr name="titleText" format="string"/>
<attr name="titleTextSize" format="dimension"/>
<attr name="titleTextColor" format="color"/>
<attr name="leftBackground" format="reference|color"/>
<attr name="leftText" format="string"/>
<attr name="leftTextColor" format="reference|color"/>
<attr name="rightBackground" format="reference|color"/>
<attr name="rightText" format="string"/>
<attr name="rightTextColor" format="reference|color"/>
</declare-styleable>

</resources>


关于这个文件,需要解释的有以下几点:

1.<declare-styleable>这个标签是针对控件属性的,所以要死记硬背;
2.name="Topbar"这个属性是整个自定义控件的名称,后面的代码中会引用到;
3.<attr name="titleText" format="string"/>中的name就是属性的名称,format是属性值的类型,这里就是string,需要强调的是,eclipse中没有提示,需要自己百度查。

第二步,新建Topbar.class

public class TopBar extends RelativeLayout {
private float titleTextSize;
private int titleTextColor;
private String titleText;
private Drawable leftBackground;
private int leftTextColor;
private String rightText;
private Drawable rightBackground;
private int rightTextColor;
private String leftText;
private LayoutParams leftParams, rightParams, titleParams;
private topbarClickListener listener;
//定义Listener的接口
public interface topbarClickListener{
public void leftClick();
public void rightClick();
}
public void setOnTopbarClickListener(topbarClickListener listener){
this.listener = listener;
}
public MyTopBar(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.Topbar);//将xml中属性转换成数组
titleTextSize = ta.getDimension(R.styleable.Topbar_titleTextSize, 0);//获取相应属性值
titleTextColor = ta.getColor(R.styleable.Topbar_titleTextColor, 0);
titleText = ta.getString(R.styleable.Topbar_titleText);

leftBackground = ta.getDrawable(R.styleable.Topbar_leftBackground);
leftText = ta.getString(R.styleable.Topbar_leftText);
leftTextColor = ta.getColor(R.styleable.Topbar_leftTextColor, 0);

rightBackground = ta.getDrawable(R.styleable.Topbar_rightBackground);
rightText = ta.getString(R.styleable.Topbar_rightText);
rightTextColor = ta.getColor(R.styleable.Topbar_rightTextColor, 0);
ta.recycle();
TextView title = new TextView(context);//新建基础控件
Button leftButton = new Button(context);
Button rightButton = new Button(context);
title.setText(titleText);//将属性值赋值给新建的基础控件
title.setBackgroundColor(titleTextColor);
title.setTextSize(titleTextSize);

leftButton.setText(leftText);
leftButton.setBackground(leftBackground);
leftButton.setBackgroundColor(leftTextColor);

rightButton.setText(rightText);
rightButton.setBackground(rightBackground);
rightButton.setBackgroundColor(rightTextColor);

setBackgroundColor(0x7CFC0055);//整个控件的背景色
titleParams = new LayoutParams(
android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
android.view.ViewGroup.LayoutParams.MATCH_PARENT);//设定控件的宽和高
titleParams.addRule(RelativeLayout.CENTER_IN_PARENT, TRUE);//设定控件的位置,CENTER_IN_PARENT指的是在父类空间的中间
addView(title, titleParams);//最后是将设定好的基础控件加在自定义控件中

leftParams = new LayoutParams(
android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, TRUE);
addView(leftButton, leftParams);

rightParams = new LayoutParams(
android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
rightParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, TRUE);
addView(rightButton,rightParams);

//设定左边按钮的点击事件
leftButton.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
listener.leftClick();
}
});
rightButton.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
listener.rightClick();
}
});
}

}


上面的代码已经将功能全部实现,包括属性值的转换、将属性值赋值给控件,点击事件等等步骤,慢慢消化吧。自定义控件的工作基本完成,剩下的就是使用了。关于这个自定义控件的使用,还有几点需要强调的。



1.需要添加这么一段引用代码,其中custombar是自己定义的,和3中的custombar相对应;
2.自定义控件的标签需要将包名也写上,Topbar指的是上面写的Topbar.class的文件名;
3.因为rightText这个属性值是自定义添加的,所以要用custombar引用;

最后的最后,来一张图片,看看自定义控件的效果吧。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: