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

为android自定义View控件添加自定义的属性

2015-07-05 20:18 555 查看
主要步骤:

1、在attrs.xml文件中声明属性,有属性名:name和格式:format 。如:

<declare-styleable name="MyToggleBtn">
<attr  name="current_state" format="boolean"/>
</declare-styleable>


2、在布局文件中使用新属性,使用之前必须先声明命名空间,如:xmlns:heima="http://schemas.android.com/apk/res/com.itheima.mytogglebtn"

3、在自定义view的构造方法当中,通过解析 AttributeSet 对象,获得所需要的属性值。

一、在attrs.xml文件中声明属性,如:

<declare-styleable name="MyToggleBtn">    //声名属性集的名称,即这些属性是属于哪个控件的。
<attr name="current_state" format="boolean"/>    //声名属性 current_state  格式为 boolean 类型
<attr name="slide_button" format="reference"/>    //声名属性 slide_button  格式为 reference 类型
</declare-styleable>


所有的format类型,详见注1:

二、在布局文件中使用:在使用之前必须声名命名空间,xmlns:heima="http://schemas.android.com/apk/res/com.itheima.mytogglebtn"

说明:xmlns 是XMLname space 的缩写;

heima 可为任意写符
http://schemas.android.com/apk/res/ 此为android固定格式;

com.itheima.mytogglebtn 此应用的包名,如manifest配置文件中一致。

布局文件:

<com.itheima.mytogglebtn.MyToggleButton

xmlns:heima="http://schemas.android.com/apk/res/com.itheima.mytogglebtn"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

heima:slide_button="@drawable/slide_button" />

三、在代码中对属性进行解析,主要代码:

TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.MyToggleBtn); // 由attrs 获得TypeArray

注1:

format 常用类型

reference 引用

color 颜色

boolean 布尔值

dimension 尺寸值

float 浮点值

integer 整型值

string 字符串

enum 布尔值

附一完整的自定义控件实现

public class MyToggleButton extends View implements OnClickListener{

/**
* 做为背景的图片
*/
private Bitmap backgroundBitmap;
/**
* 可以滑动的图片
*/
private Bitmap slideBtn;
private Paint paint;
/**
* 滑动按钮的左边届
*/
private float slideBtn_left;
/**
* 背景图的资源ID
*/
private int backgroundId;
/**
* 滑动图片的资源ID
*/
private int slideBtnId;

/**
* 在代码里面创建对象的时候,使用此构造方法
*/
public MyToggleButton(Context context) {
super(context);
// TODO Auto-generated constructor stub
}

/**
* 在布局文件中声名的view,创建时由系统自动调用。
* @param context	上下文对象
* @param attrs		属性集
*/
public MyToggleButton(Context context, AttributeSet attrs) {
super(context, attrs);

//无命名空间测试

String testAttrs = attrs.getAttributeValue(null, "testAttrs");

System.out.println("testAttrs===:"+testAttrs);

//获得自定义的属性
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyToggleBtn);

int N = ta.getIndexCount();
for (int i = 0; i < N; i++) {
/*
* 获得某个属性的ID值
*/
int itemId = ta.getIndex(i);
switch (itemId) {
case R.styleable.MyToggleBtn_curr_state:
currState = ta.getBoolean(itemId, false);

break;
case R.styleable.MyToggleBtn_my_background:
backgroundId = ta.getResourceId(itemId, -1);
if(backgroundId == -1){
throw new RuntimeException("请设置背景图片");
}
backgroundBitmap = BitmapFactory.decodeResource(getResources(), backgroundId);

break;
case R.styleable.MyToggleBtn_my_slide_btn:
slideBtnId = ta.getResourceId(itemId, -1);
slideBtn = BitmapFactory.decodeResource(getResources(), slideBtnId);

break;

default:
break;
}

}

initView();
}

/**
* 初始化
*/
private void initView() {
//初始化图片
//		backgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.switch_background);
//		slideBtn = BitmapFactory.decodeResource(getResources(), R.drawable.slide_button);

//初始化 画笔
paint = new Paint();
paint.setAntiAlias(true); // 打开抗矩齿

//添加onclick事件监听
setOnClickListener(this);

flushState();
}

/*
* view 对象显示的屏幕上,有几个重要步骤:
* 1、构造方法 创建 对象。
* 2、测量view的大小。	onMeasure(int,int);
* 3、确定view的位置 ,view自身有一些建议权,决定权在 父view手中。  onLayout();
* 4、绘制 view 的内容 。 onDraw(Canvas)
*/

@Override
/**
* 测量尺寸时的回调方法
*/
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//		super.onMeasure(widthMeasureSpec, heightMeasureSpec);

/**
* 设置当前view的大小
* width  :view的宽度
* height :view的高度   (单位:像素)
*/
setMeasuredDimension(backgroundBitmap.getWidth(),backgroundBitmap.getHeight());
}

//确定位置的时候调用此方法
//自定义view的时候,作用不大
//	@Override
//	protected void onLayout(boolean changed, int left, int top, int right,
//			int bottom) {
//		super.onLayout(changed, left, top, right, bottom);
//	}

/**
* 当前开关的状态
*  true 为开
*/
private boolean currState = false;

@Override
/**
* 绘制当前view的内容
*/
protected void onDraw(Canvas canvas) {
//		super.onDraw(canvas);

// 绘制 背景
/*
* backgroundBitmap	要绘制的图片
* left	图片的左边届
* top	图片的上边届
* paint 绘制图片要使用的画笔
*/
canvas.drawBitmap(backgroundBitmap, 0, 0, paint);

//绘制 可滑动的按钮
canvas.drawBitmap(slideBtn, slideBtn_left, 0, paint);
}

/**
* 判断是否发生拖动,
* 如果拖动了,就不再响应 onclick 事件
*
*/
private boolean isDrag = false;
@Override
/**
* onclick 事件在View.onTouchEvent 中被解析。
* 系统对onclick 事件的解析,过于简陋,只要有down 事件  up 事件,系统即认为 发生了click 事件
*
*/
public void onClick(View v) {
/*
* 如果没有拖动,才执行改变状态的动作
*/
if(!isDrag){
currState = !currState;
flushState();
}
}

/**
* down 事件时的x值
*/
private int firstX;
/**
* touch 事件的上一个x值
*/
private int lastX;

@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);

switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
firstX = lastX =(int) event.getX();
isDrag = false;

break;
case MotionEvent.ACTION_MOVE:

//判断是否发生拖动
if(Math.abs(event.getX()-firstX)>5){
isDrag = true;
}

//计算 手指在屏幕上移动的距离
int dis = (int) (event.getX() - lastX);

//将本次的位置 设置给lastX
lastX = (int) event.getX();

//根据手指移动的距离,改变slideBtn_left 的值
slideBtn_left = slideBtn_left+dis;
break;
case MotionEvent.ACTION_UP:

//在发生拖动的情况下,根据最后的位置,判断当前开关的状态
if (isDrag) {

int maxLeft = backgroundBitmap.getWidth() - slideBtn.getWidth(); // slideBtn
// 左边届最大值
/*
* 根据 slideBtn_left 判断,当前应是什么状态
*/
if (slideBtn_left > maxLeft / 2) { // 此时应为 打开的状态
currState = true;
} else {
currState = false;
}

flushState();
}
break;
}

flushView();

return true;
}

/**
* 刷新当前状态
*/
private void flushState() {
if(currState){
slideBtn_left = backgroundBitmap.getWidth()-slideBtn.getWidth();
}else{
slideBtn_left = 0;
}

flushView();
}

/**
* 刷新当前视力
*/
private void flushView() {
/*
* 对 slideBtn_left  的值进行判断 ,确保其在合理的位置 即       0<=slideBtn_left <=  maxLeft
*
*/

int maxLeft = backgroundBitmap.getWidth()-slideBtn.getWidth();	//	slideBtn 左边届最大值

//确保 slideBtn_left >= 0
slideBtn_left = (slideBtn_left>0)?slideBtn_left:0;

//确保 slideBtn_left <=maxLeft
slideBtn_left = (slideBtn_left<maxLeft)?slideBtn_left:maxLeft;

/*
* 刷新当前视图  导致 执行onDraw执行
*/
invalidate();
}

}


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