MyToggleView.java
package com.example.test;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* 自定义开关按钮 android绘制界面的流程:
* onMeasure(测量:指定view的宽和高)--->onLayout(摆放view的位置)---->onDraw(绘制内容),
* 如果要实现自定义控件,就要重写这些方法,这些方法在onResume方法之后执行
*
* 如果是继承View,那么只需要重写onMeasure和onDraw方法
* 如果是继承ViewGroup,那么需要重写onMeasure,onLayout,onDraw方法
*
* @author Administrator
*
*/
public class MyToggleView extends View {
private Bitmap switchBackgroundBitmap; // 开关的背景图片
private Paint paint; // 画笔对象
private Bitmap slideButtonBitmap; // 滑动开关的图片
boolean mSwitchState; // 设置开关的状态
float currentX; //触摸滑动按钮时,获取滑动按钮的x坐标
boolean isTouchingSlideButton = false; // 是否触摸滑动按钮
private OnSwitchStateChangedListener onSwitchStateChangedListener;
public MyToggleView(Context context) {
super(context);
init();
}
public MyToggleView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyToggleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public void init() {
paint = new Paint();//新建画笔对象
}
// 测量自定义开关的背景图片的宽度和高度
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(switchBackgroundBitmap.getWidth(),
switchBackgroundBitmap.getHeight());
}
// 绘制自定义开关
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制开关的背景图片
canvas.drawBitmap(switchBackgroundBitmap, 0, 0, paint);
// 绘制滑动按钮的图片
if (isTouchingSlideButton) {// 正在触摸滑动按钮
// 让滑块向左移动自身一半大小的位置
float newLeft = currentX - slideButtonBitmap.getWidth() / 2.0f;
float maxLeft = switchBackgroundBitmap.getWidth()
- slideButtonBitmap.getWidth();
// 限制滑动按钮的水平方向的范围
if (newLeft < 0) {// 限制左边的范围
newLeft = 0;
}
if (newLeft > maxLeft) {// 限制右边的范围
newLeft = maxLeft;
}
canvas.drawBitmap(slideButtonBitmap, newLeft, 0, paint);
} else {
// //根据开关的状态来绘制滑动按钮图片
if (mSwitchState) {// 如果开关为开的时候,距离左边的距离为=背景图片的宽度-滑动按钮的宽度
int left = switchBackgroundBitmap.getWidth()
- slideButtonBitmap.getWidth();
canvas.drawBitmap(slideButtonBitmap, left, 0, paint);
} else {// 如果开关为关闭的时候,距离左边的距离就为0
canvas.drawBitmap(slideButtonBitmap, 0, 0, paint);
}
}
}
// 设置开关背景资源
public void setSwitchBackgroundResource(int id) {
switchBackgroundBitmap = BitmapFactory.decodeResource(getResources(),
id);
}
// 设置滑动按钮的资源
public void setSlideButtonResource(int slideButtonId) {
slideButtonBitmap = BitmapFactory.decodeResource(getResources(),
slideButtonId);
}
// 设置自定义开关的状态
public void setSwitchState(boolean mSwitchState) {
this.mSwitchState = mSwitchState;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isTouchingSlideButton = true;
System.out.println("---ACTION_DOWN :" + event.getX());
currentX = event.getX();
break;
case MotionEvent.ACTION_MOVE:
System.out.println("----ACTION_MOVE :" + event.getX());
currentX = event.getX();
break;
case MotionEvent.ACTION_UP:
isTouchingSlideButton = false;
System.out.println("----ACTION_UP :" + event.getX());
currentX = event.getX();
float center = switchBackgroundBitmap.getWidth() / 2.0f;
boolean currentSwitchState = currentX > center;
if (currentSwitchState != mSwitchState
&& onSwitchStateChangedListener != null) {
onSwitchStateChangedListener.onStateChanged(currentSwitchState);
}
mSwitchState = currentSwitchState;
break;
}
invalidate();// 重绘view,即重写调用onDraw方法
return true;// 返回true,才响应触摸事件
}
public interface OnSwitchStateChangedListener {
// 状态回调,将当前开关的状态传到UI界面上去
public void onStateChanged(boolean state);
}
public void setOnSwitchStateChanged(
OnSwitchStateChangedListener onSwitchStateChangedListener) {
this.onSwitchStateChangedListener = onSwitchStateChangedListener;
}
}
实验截图: