在Android4.0中也添加了一个类似的控件:Switch。如下图所示:



Android自定义Switch开关_android



其类关系图如下:


Android自定义Switch开关_滑块_02


这种控件使用起来很简单,但有一定的局限性:


1. 必须在4.0以上的系统中才能使用


2. 原生的UI不太美观


因此,基于上面两点,自定义Switch成为了首选。


SwitchButton.java


package com.jackie.countdowntimer;

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

/**
* Created by Jackie on 2015/12/15.
*/
public class SwitchButton extends View {
private Bitmap mSwitchBackgroud, mSlideBackground;

private int mCurrentX; //当前X轴偏移量
private boolean mCurrentState = false; //当前状态,判断滑块是否滑动成功
private boolean mIsSliding = false; //滑块是否正在滑动

private OnSwitchStateChangeListener mOnSwitchStateChangeListener; //状态改变的回调

public SwitchButton(Context context, AttributeSet attrs) {
super(context, attrs);

initBitmap();
}

//初始化开关图片
private void initBitmap() {
mSwitchBackgroud = BitmapFactory.decodeResource(getResources(), R.drawable.switch_background);
mSlideBackground = BitmapFactory.decodeResource(getResources(), R.drawable.slide_button_background);
}

//设置当前控件的宽和高
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

// 设置开关的宽和高
setMeasuredDimension(mSwitchBackgroud.getWidth(), mSwitchBackgroud.getHeight());
}

@Override
protected void onDraw(Canvas canvas) {
//绘制背景
canvas.drawBitmap(mSwitchBackgroud, 0, 0, null);

if (mIsSliding) { //正在滑动中
int left = mCurrentX - mSlideBackground.getWidth();
if (left < 0) { //超过左边界
left = 0;
} else if (left > mSwitchBackgroud.getWidth() - mSlideBackground.getWidth()) { //超出右边界
left = mSwitchBackgroud.getWidth() - mSlideBackground.getWidth();
}

canvas.drawBitmap(mSlideBackground, left, 0, null);
} else {
if (mCurrentState) {
//绘制开关开的状态
int left = mSwitchBackgroud.getWidth() - mSlideBackground.getWidth();
canvas.drawBitmap(mSlideBackground, left, 0, null);
} else {
//绘制开关关的状态
canvas.drawBitmap(mSlideBackground, 0, 0, null);
}
}

super.onDraw(canvas);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mCurrentX = (int) event.getX();
mIsSliding = true;
break;
case MotionEvent.ACTION_MOVE:
mCurrentX = (int) event.getX();
break;
case MotionEvent.ACTION_UP:
mCurrentX = (int) event.getX();
mIsSliding = false;

int center = mSwitchBackgroud.getWidth() / 2;
boolean state = mCurrentX > center; //滑块滑动的距离超过背景的一半,表示滑动成功,状态需要改变

if (mCurrentState != state && mOnSwitchStateChangeListener != null) { //两个状态不一样,表示滑动已经滑动成功,状态改变
mOnSwitchStateChangeListener.onSwitchStateChange(state);
}

mCurrentState = state;
break;
}

invalidate();
return true;
}

/**
* 设置开关的状态
* @param state
*/
public void setSwitchState(boolean state) {
mCurrentState = state;
}

public void setOnSwitchStateChangeListener(OnSwitchStateChangeListener onSwitchStateChangeListener) {
this.mOnSwitchStateChangeListener = onSwitchStateChangeListener;
}
}


OnSwitchStateChangeListener.java

package com.jackie.countdowntimer;

/**
* Created by Jackie on 2015/12/15.
*/
public interface OnSwitchStateChangeListener {
/**
* 当开关状态改变时回调此方法
* @param state 开关当前的状态
*/
void onSwitchStateChange(boolean state);
}


<com.jackie.countdowntimer.SwitchButton
android:id="@+id/switcher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/verify_code"
/>

使用方法:


mSwitchButton = (SwitchButton) findViewById(R.id.switcher);
mSwitchButton.setSwitchState(true);
mSwitchButton.setOnSwitchStateChangeListener(new OnSwitchStateChangeListener() {
@Override
public void onSwitchStateChange(boolean state) {
if (state) {
Toast.makeText(MainActivity.this, "开关打开了", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "开关关闭了", Toast.LENGTH_SHORT).show();
}
}
});


最后附上所用的资源图片:


Android自定义Switch开关_android_03

   

Android自定义Switch开关_ide_04


效果图如下:

Android自定义Switch开关_滑块_05