自定义控件:开关按钮的实现

自定义点击开关按钮

一、继承已有View实现自定义View
通过对android原生控件的研究,可以发现android中的控件都是继承view类,如textView、ImageView等,通过重写相关的方法来实现新的果,通过这个我们得到两点:
1.我们可以在已有控件的基础上,通过重写相关方法来实现我们的需求。
2.继承view类或viewgroup类,来创建我们所需要的控件。一般来讲,通过继承已有的控件,来自定义控件要简单一点。

/**
 * 自定义按钮
 * @author afu
 */
public class MyToggleButton extends View {

	// 增加一个默认显示样式时候使用
	public MyToggleButton(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	// 在布局文件中声明view的时候,该方法有系统调用
	public MyToggleButton(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	// 在代码中new实例化时调用
	public MyToggleButton(Context context) {
		super(context);
	}

}
布局文件activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.xbmu.toggle.MyToggleButton
        android:layout_marginTop="50dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true" />

</RelativeLayout>
二、一个View从创建到显示屏幕的步骤
1.执行view构造方法,创建对象
2.测量view大小
    onMeasure(int,int);来完成测量动作
3.指定view的位置,子View只有建议权,父View才有决定权;
onLayout(boolean,int,int,int ,int);
这个方法一般用不着,如果自定义ViewGoup才用到
4.绘制view的内容
onDraw(canvas);
三、画个矩形背景和圆形
package com.xbmu.togglebutton;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

/**
 * 自定按钮
 * @author afu
 */
public class MyToggleButton extends View {
	
	/**
	 * 一个View从创建到显示屏幕上的主要步骤:
	 * 1.执行view构造方法,创建对象
	 * 2.测量view大小
	 *  onMeasure(int,int);来完成测量动作
	 * 3.指定view的位置,子View只有建议权,父View才有决定权;
	 * onLayout(boolean,int,int,int ,int);
	 * 这个方法一般用不着,如果自定义ViewGoup才用到
	 * 4.绘制view的内容
	 * onDraw(canvas);
	 * 
	 */
	
	private Paint paint;

	/**
	 * 测量
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		//设置当前view的测量大小
		setMeasuredDimension(100, 100);
	}
	/**
	 * 绘制
	 */
	@Override
	protected void onDraw(Canvas canvas) {
//		super.onDraw(canvas);
		//绘制颜色,可以理解成背景颜色
		canvas.drawColor(Color.RED);
		//绘制圆形
		canvas.drawCircle(50, 50, 20, paint);
	}
	
	private void init(Context context) {
		paint = new Paint();
		paint.setColor(Color.GREEN);
		//设置抗锯齿,让边缘圆滑,一般都会设置
		paint.setAntiAlias(true);
		
	}
	// 增加一个默认显示样式时候使用
	public MyToggleButton(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context);
	}

	// 在布局文件中声明view的时候,该方法有系统调用
	public MyToggleButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	// 在代码中new实例化时调用
	public MyToggleButton(Context context) {
		super(context);
		init(context);
	}
	

}
四、画按钮背景
package com.xbmu.togglebutton;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;

/**
 * 自定按钮
 * @author afu
 */
public class MyToggleButton extends View {
	
	/**
	 * 一个View从创建到显示屏幕上的主要步骤:
	 * 1.执行view构造方法,创建对象
	 * 2.测量view大小
	 *  onMeasure(int,int);来完成测量动作
	 * 3.指定view的位置,子View只有建议权,父View才有决定权;
	 * onLayout(boolean,int,int,int ,int);
	 * 这个方法一般用不着,如果自定义ViewGoup才用到
	 * 4.绘制view的内容
	 * onDraw(canvas);
	 * 
	 */
	
	private Paint paint;
	private Bitmap backGroundBitmap;
	private Bitmap slideBitmap;
	private Context context;

	/**
	 * 测量
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		//设置当前view的测量大小
		setMeasuredDimension(backGroundBitmap.getWidth(), backGroundBitmap.getHeight());
	}
	/**
	 * 绘制
	 */
	@Override
	protected void onDraw(Canvas canvas) {
//		super.onDraw(canvas);
		//绘制颜色,可以理解成背景颜色
//		canvas.drawColor(Color.RED);
		//绘制圆形
//		canvas.drawCircle(50, 50, 20, paint);
		canvas.drawBitmap(backGroundBitmap, 0, 0, paint);
	}
	
	private void init(Context context) {
		this.context = context;
		paint = new Paint();
		paint.setColor(Color.GREEN);
		//设置抗锯齿,让边缘圆滑,一般都会设置
		paint.setAntiAlias(true);
		
		//初始化图片-从资源文件中解析成Bitmap对象
		slideBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.slide_button);
		backGroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.switch_background);
		
	}
	// 增加一个默认显示样式时候使用
	public MyToggleButton(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context);
	}

	// 在布局文件中声明view的时候,该方法有系统调用
	public MyToggleButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	// 在代码中new实例化时调用
	public MyToggleButton(Context context) {
		super(context);
		init(context);
	}	
}
五、画滑动按钮
canvas.drawBitmap(slideBitmap, 45, 0, paint);
分别设置0和30运行看看效果
六、点击时改变按钮状态
package com.itheima.togglebutton;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;

/**
 * 自定按钮
 * @author afu
 */
public class MyToggleButton extends View implements  View.OnClickListener {
	
	/**
	 * 一个View从创建到显示屏幕上的主要步骤:
	 * 1.执行view构造方法,创建对象
	 * 2.测量view大小
	 *  onMeasure(int,int);来完成测量动作
	 * 3.指定view的位置,子View只有建议权,父View才有决定权;
	 * onLayout(boolean,int,int,int ,int);
	 * 这个方法一般用不着,如果自定义ViewGoup才用到
	 * 4.绘制view的内容
	 * onDraw(canvas);
	 * 
	 */
	
	private Paint paint;
	private Bitmap backGroundBitmap;
	private Bitmap slideBitmap;
	private Context context;
	/**
	 * 距离左边的距离
	 */
	private float slideLeft;
	/**
	 * 判断当前开关状态
	 * true为开
	 * false为关
	 */
	private boolean curStata = false;

	/**
	 * 测量
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		//设置当前view的测量大小
		setMeasuredDimension(backGroundBitmap.getWidth(), backGroundBitmap.getHeight());
	}
	/**
	 * 绘制
	 */
	@Override
	protected void onDraw(Canvas canvas) {
//		super.onDraw(canvas);
		//绘制颜色,可以理解成背景颜色
//		canvas.drawColor(Color.RED);
		//绘制圆形
//		canvas.drawCircle(50, 50, 20, paint);
		canvas.drawBitmap(backGroundBitmap, 0, 0, paint);
		//绘制滑动按钮
		canvas.drawBitmap(slideBitmap, slideLeft, 0, paint);
	}
	
	private void init(Context context) {
		this.context = context;
		paint = new Paint();
		paint.setColor(Color.GREEN);
		//设置抗锯齿,让边缘圆滑,一般都会设置
		paint.setAntiAlias(true);
		
		//初始化图片-从资源文件中解析成Bitmap对象
		slideBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.slide_button);-
		backGroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.switch_background);
		
		setOnClickListener( MyToggleButton.this);
		
	}
	// 增加一个默认显示样式时候使用
	public MyToggleButton(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context);
	}

	// 在布局文件中声明view的时候,该方法有系统调用
	public MyToggleButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	// 在代码中new实例化时调用
	public MyToggleButton(Context context) {
		super(context);
		init(context);
	}
	
	@Override
	public void onClick(View v) {
		curStata = !curStata;
		flushState();
		
	}
	/**
	 * 刷新状态
	 */
	private void flushState() {
		//设置距离左边的距离
		if(curStata){
			slideLeft = backGroundBitmap.getWidth()-slideBitmap.getWidth();
		}else{
			slideLeft = 0;
		}
		
		/**
		 * 刷新View,会导致当前View的onDraw方法执行
		 */
		invalidate();
	}
}
运行效果图:

自定义滑动开关按钮

一、实现滑动效果:
/**
 * 第一次按下的x坐标
 */
int startX = 0;
@Override
public boolean onTouchEvent(MotionEvent event) {
	super.onTouchEvent(event);
	switch (event.getAction()) {
	case MotionEvent.ACTION_DOWN://按下
		//1.记录第一次按下坐标
		startX = (int) event.getRawX();
		break;
	case MotionEvent.ACTION_MOVE://滑动
		//2.来到新的坐标
		int newX = (int) event.getRawX();
		//3.计算偏移量
		int dX = newX - startX;
		slideLeft += dX;
		//4.更新UI-onDraw方法即可--invalidate();
		invalidate();
		//5.重新记录坐标
		startX = (int) event.getRawX();
		break;
	case MotionEvent.ACTION_UP://离开
		break;
	}		
	return true;
}
看运行效果图,但是存在bug:
自定义控件:开关按钮的实现_第1张图片
二、取消点击事件,屏蔽非法滑动:
public class MyToggleButton extends View implements OnClickListener {

	private Paint paint;

	/**
	 * 一个View从创建到显示到屏幕过程中的步骤
	 *1.执行View的构造方法,实例化;通常在构造方法里面加载资源 
	 *2.测量view对象
	 * onMeasure(int,int) 
	 *3.指定View的位置 - 一般的View用不到,自定义包括其他View进来这样的控才用到
	 * onLayout(boolean,int,int,int,int) 
	 *4.绘制View对象 onDraw(canvas)
	 * 
	 */

	private Bitmap backgroundBitmap;
	private Bitmap slideBitmap;

	/**
	 * 滑动图片,距离左边的距离
	 */
	private float slideLeft;
	/**
	 * 按钮的状态 false为关闭 true为开
	 */
	private boolean curState = false;

	// 测量
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		// 设置测量值
		setMeasuredDimension(backgroundBitmap.getWidth(),
				backgroundBitmap.getHeight());
	}

	// 绘制
	@Override
	protected void onDraw(Canvas canvas) {
		// super.onDraw(canvas);
		// canvas.drawColor(Color.GREEN);
		// canvas.drawCircle(50, 50, 20, paint);
		canvas.drawBitmap(backgroundBitmap, 0, 0, paint);
		canvas.drawBitmap(slideBitmap, slideLeft, 0, paint);
	}
	/**
	 * 第一次按下的x坐标
	 */
	int startX = 0;
	int maxLeft;
	

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		super.onTouchEvent(event);
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN://按下
			//1.记录第一次按下坐标
			startX = (int) event.getRawX();

			break;
		case MotionEvent.ACTION_MOVE://滑动
			//2.来到新的坐标
			int newX = (int) event.getRawX();
			//3.计算偏移量
			int dX = newX - startX;
			slideLeft += dX;
			//4.更新UI-onDraw方法即可--invalidate();
			flushView();
			//5.重新记录坐标
			startX = (int) event.getRawX();
			break;
		case MotionEvent.ACTION_UP://离开

			break;

		default:
			break;
		}
		
		return true;
	}

  // 刷新View的状态,并且纠正非法滑动
	private void flushView() {
		if(slideLeft < 0){
			slideLeft = 0;
		}
		
		if(slideLeft > maxLeft){
			slideLeft = maxLeft;
		}
		//屏蔽非法滑动
		invalidate();
	}

	private void init(Context context) {
		paint = new Paint();
		paint.setColor(Color.RED);
		// 设置抗锯齿-使其变得光滑
		paint.setAntiAlias(true);
		// 加载资源图片
		backgroundBitmap = BitmapFactory.decodeResource(getResources(),
				R.drawable.switch_background);
		slideBitmap = BitmapFactory.decodeResource(getResources(),
				R.drawable.slide_button);
		
		//滑动图片距离左边的距离
		maxLeft = backgroundBitmap.getWidth()-slideBitmap.getWidth();

		// 设置点击事件
//		setOnClickListener(this);
	}

	// 一般会在代码中实例化
	public MyToggleButton(Context context) {
		super(context);
		init(context);
	}

	// 带有两个参数的构造方法,在布局文件中使用的时候,就会回调
	public MyToggleButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	// 我们需要设置默认的样式风格的时候
	public MyToggleButton(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context);
	}

	@Override
	public void onClick(View v) {
		curState = !curState;

		flushState();
	}

	// 刷新View的状态
	private void flushState() {
		if (curState) {
			
			slideLeft = maxLeft;
		} else {
			slideLeft = 0;
		}
		flushView();
	}
}
自定义控件:开关按钮的实现_第2张图片

三、处理滑动到一小半时时不好看的问题
先画图分析:
自定义控件:开关按钮的实现_第3张图片

@Override
public boolean onTouchEvent(MotionEvent event) {
	super.onTouchEvent(event);
	switch (event.getAction()) {
	case MotionEvent.ACTION_DOWN://按下
		//1.记录第一次按下坐标
		startX = (int) event.getRawX();
		break;
	case MotionEvent.ACTION_MOVE://滑动
		//2.来到新的坐标
		int newX = (int) event.getRawX();
		//3.计算偏移量
		int dX = newX - startX;
		slideLeft += dX;
		//4.更新UI-onDraw方法即可--invalidate();
		flushView();
		//5.重新记录坐标
		startX = (int) event.getRawX();
	break;
	case MotionEvent.ACTION_UP://离开
		/**
		 *  当UP事件发生的时候,由按钮的左边距离(btn_left)确定View的状态;
			当btn_left >= maxLeft/2 设置为开状态
			当btn_left < maxLeft/2  设置为 关闭状态
		 */
		if(slideLeft >= maxLeft/2){
			curState = true;
		}else{
			curState = false;
		}
		flushState();
		break;

	}
		
	return true;
}
恢复点击事件
演示会有bug
自定义控件:开关按钮的实现_第4张图片
四、解决点击事件和滑动事件导致的bug
public class MyToggleButton extends View implements OnClickListener {

	private Paint paint;

	/**
	 * 一个View从创建到显示到屏幕过程中的步骤:
	 *1.执行View的构造方法,实例化;通常在构造方法里面加载资源 
	 *2.测量view对象
	 * onMeasure(int,int) 
	 *3.指定View的位置 - 一般的View用不到,自定义包括其他View进来这样的控才用到
	 * onLayout(boolean,int,int,int,int)
	 *4.绘制View对象 onDraw(canvas)
	 * 
	 */

	private Bitmap backgroundBitmap;
	private Bitmap slideBitmap;

	/**
	 * 滑动图片,距离左边的距离
	 */
	private float slideLeft;
	/**
	 * 按钮的状态 false为关闭 true为开
	 */
	private boolean curState = false;

	// 测量
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		// 设置测量值
		setMeasuredDimension(backgroundBitmap.getWidth(),
				backgroundBitmap.getHeight());
	}

	// 绘制
	@Override
	protected void onDraw(Canvas canvas) {
		// super.onDraw(canvas);
		// canvas.drawColor(Color.GREEN);
		// canvas.drawCircle(50, 50, 20, paint);
		canvas.drawBitmap(backgroundBitmap, 0, 0, paint);
		canvas.drawBitmap(slideBitmap, slideLeft, 0, paint);
	}
	/**
	 * 第一次按下的x坐标
	 */
	int startX = 0;
	/**
	 * 最初的历史位置
	 */
	int lastX = 0;
	/**
	 * 滑动按钮距离左边的最大距离
	 */
	int maxLeft;
	/**
	 * 点击事件是否可用
	 * true 可用
	 * false 不可用
	 */
	boolean isClickEnable = true;
	

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		super.onTouchEvent(event);
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN://按下
			//1.记录第一次按下坐标
			lastX = startX = (int) event.getRawX();
			isClickEnable = true;
			break;
		case MotionEvent.ACTION_MOVE://滑动
			//2.来到新的坐标
			int newX = (int) event.getRawX();
			//3.计算偏移量
			int dX = newX - startX;
			slideLeft += dX;
			//4.更新UI-onDraw方法即可--invalidate();
			if(Math.abs(event.getRawX()-lastX)>5){
				isClickEnable = false;
			}
			flushView();
			//5.重新记录坐标
			startX = (int) event.getRawX();
			break;
		case MotionEvent.ACTION_UP://离开
			
			if(!isClickEnable){
				/**
				 *  当UP事件发生的时候,由按钮的左边距离(btn_left)确定View的状态;
					当btn_left >= maxLeft/2 设置为开状态
					当btn_left < maxLeft/2  设置为 关闭状态
				 */
				
				if(slideLeft >= maxLeft/2){
					curState = true;
				}else{
					curState = false;
				}
				flushState();
			}
			
			break;

		default:
			break;
		}
		
		return true;
	}

  // 刷新View的状态,并且纠正非法滑动
	private void flushView() {
		if(slideLeft < 0){
			slideLeft = 0;
		}
		
		if(slideLeft > maxLeft){
			slideLeft = maxLeft;
		}
		//屏蔽非法滑动
		invalidate();
	}

	private void init(Context context) {
		paint = new Paint();
		paint.setColor(Color.RED);
		// 设置抗锯齿-使其变得光滑
		paint.setAntiAlias(true);
		// 加载资源图片
		backgroundBitmap = BitmapFactory.decodeResource(getResources(),
				R.drawable.switch_background);
		slideBitmap = BitmapFactory.decodeResource(getResources(),
				R.drawable.slide_button);
		
		//滑动图片距离左边的距离
		maxLeft = backgroundBitmap.getWidth()-slideBitmap.getWidth();

		// 设置点击事件
		setOnClickListener(this);
	}

	// 一般会在代码中实例化
	public MyToggleButton(Context context) {
		super(context);
		init(context);
	}

	// 带有两个参数的构造方法,在布局文件中使用的时候,就会回调
	public MyToggleButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	// 我们需要设置默认的样式风格的时候
	public MyToggleButton(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context);
	}

	@Override
	public void onClick(View v) {
		if(isClickEnable){
			curState = !curState;

			flushState();
		}
		
	}

	// 刷新View的状态
	private void flushState() {
		if (curState) {
			
			slideLeft = maxLeft;
		} else {
			slideLeft = 0;
		}
		flushView();
	}
}
自定义控件:开关按钮的实现_第5张图片

 
   

全部代码:

package com.xbmu.toggle;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
 * 1.执行view构造方法,创建对象 2.测量view大小 onMeasure(int,int)来完成测量动作
 * 3.指定view的位置,子View只有建议权,父View才有决定权; onLayout(boolean,int,int,int,int);
 * 这个方法一般用不着,如果自定义ViewGroup才用到 4.绘制View的内容 onDraw(canvas)
 * 
 */
public class MyToggleButton extends View implements View.OnClickListener {
	// 定义绘制(画笔)对象
	private Paint paint;
	private Bitmap slideBitmap;
	private Bitmap backGroundBitmap;
	private Context context;
	/**
	 * 距离左边的距离
	 */
	private float slideLeft;
	/**
	 * 判断当前开关状态 true为开 false为关
	 */
	private boolean curState = false;
	/**
	 * 第一次按下的x坐标
	 */
	int startX = 0;
	int maxLeft;
	/**
	 * 最初的历史位置
	 */
	int lastX = 0;
	/**
	 * 点击事件是否可用
	 * true可用
	 * false不可用
	 */
	boolean isClickEnable = true;
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		super.onTouchEvent(event);
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN://按下
			//1.记录第一次按下坐标
			startX = (int) event.getRawX();
			isClickEnable = true;
			break;
		case MotionEvent.ACTION_MOVE://滑动
			//2.来到新的坐标
			int newX = (int) event.getRawX();
			//3.计算偏移量
			int dx = newX - startX;
			slideLeft += dx;
			//4.更新UI-onDraw方法即可--invalidate();
			if(Math.abs(event.getRawX()-lastX) > 5){
				isClickEnable = false;
			}
			flushView();
			//5.重新记录坐标
			startX = (int) event.getRawX();
			break;
		case MotionEvent.ACTION_UP://离开
			if(!isClickEnable){
				/**
				 * 当UP事件发生的时候,由按钮的左边距离(btn_left)确定View的状态;
				 * 当btn_left >= maxLeft/2设置为开状态
				 * 当btn_left < maxLeft/2设置为关状态
				 */
				if(slideLeft >= maxLeft/2){
					curState = true;
				}else{
					curState = false;
				}
				flushState();
			}
			break;
		}
		return true;
	}
	//刷新View的状态,并且纠正非法滑动
	private void flushView() {
		if(slideLeft < 0){
			slideLeft = 0;
		}
		if(slideLeft > maxLeft){
			slideLeft = maxLeft;
		}
		//屏蔽非法滑动
		invalidate();
		
	}

	/**
	 * 测量
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		// 设置当前view的测量带大小
		setMeasuredDimension(backGroundBitmap.getWidth(),
				backGroundBitmap.getHeight());
	}

	/**
	 * 绘制
	 */
	@Override
	protected void onDraw(Canvas canvas) {
		// super.onDraw(canvas);
		// 绘制颜色,可以理解成背景颜色
		// canvas.drawColor(Color.RED);
		// 绘制圆形
		// canvas.drawCircle(50, 50, 20, paint);
		canvas.drawBitmap(backGroundBitmap, 0, 0, paint);
		// 绘制滑动按钮
		canvas.drawBitmap(slideBitmap, slideLeft, 0, paint);
	}

	private void initView(Context context2) {
		paint = new Paint();
		paint.setColor(Color.GREEN);
		// 设置抗锯齿,让边缘圆滑,一般都会设置
		paint.setAntiAlias(true);

		slideBitmap = BitmapFactory.decodeResource(getResources(),
				R.drawable.slide_button);
		backGroundBitmap = BitmapFactory.decodeResource(getResources(),
				R.drawable.switch_background);
		//滑动图片距离左边的距离
		maxLeft = backGroundBitmap.getWidth()-slideBitmap.getWidth();
		
		//设置点击事件
		setOnClickListener(MyToggleButton.this);
	}

	@Override
	public void onClick(View v) {
		if(isClickEnable){
			curState = !curState;
			flushState();
		}
	}

	/**
	 * 刷新状态
	 */
	private void flushState() {
		// 设置距离左边的距离
		if (curState) {
			slideLeft = backGroundBitmap.getWidth() - slideBitmap.getWidth();
		} else {
			slideLeft = 0;
		}
		/**
		 * 刷新View,会导致当前View的onDraw方法执行
		 */
		flushView();
	}
	
	public MyToggleButton(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initView(context);
	}
	//带有两个参数的构造方法,在布局文件中使用的时候,就会回调
	public MyToggleButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView(context);
	}
	//一般会在代码中实例化
	public MyToggleButton(Context context) {
		super(context);
		initView(context);
	}
}
代码下载地址
http://download.csdn.net/detail/btt2013/9352431







你可能感兴趣的:(ToggleButton,自定义开关按钮)