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

在学会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引用;


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




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值