cri_nor.png
back_white.png
back_long.png
cri_pre.png
back_black.png
/**
* 滑动开关效果
* */
@SuppressLint("Recycle") public class SwitchButton extends View {
private final String TAG = "SwitchButton";
private Bitmap mCriNor;
private Bitmap mCriPre;
private Bitmap mBackBlack;
private Bitmap mBackWhite;
private Bitmap mBackLong;
private Bitmap mBackSlide;
private float deltX = 0;
private boolean isTouch = false;
private Rect dst;
private int thumbRadius;//thumb的半径
private int lastLength;//criNor超出空间的长度
private PorterDuffXfermode mode;
private Paint mPaint;
private ValueAnimator mAnimator;
private boolean cacheIsOpen = false;
private boolean isOpen = false;
public SwitchButton(Context context, AttributeSet attrs) {
super(context, attrs);
/*TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SwitchButton);
typedArray.recycle();*/
init();
}
private void init() {
mCriNor = BitmapFactory.decodeResource(getResources(), R.drawable.cri_nor);
mCriPre = BitmapFactory.decodeResource(getResources(), R.drawable.cri_pre);
mBackBlack = BitmapFactory.decodeResource(getResources(), R.drawable.back_black);
mBackWhite = BitmapFactory.decodeResource(getResources(), R.drawable.back_white);
mBackLong = BitmapFactory.decodeResource(getResources(), R.drawable.back_long);
dst = new Rect(0, 0, mBackWhite.getWidth(), mBackWhite.getHeight());
lastLength = mCriNor.getWidth() - mBackBlack.getWidth();
thumbRadius = (mCriNor.getWidth() - lastLength*2)/2;
mode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
mPaint = new Paint();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(mBackWhite.getWidth(), mBackWhite.getHeight());
}
@Override
protected void onDraw(Canvas canvas) {
//绘制背景
canvas.drawBitmap(mBackWhite, new Matrix(), null);
//绘制滑动背景图
drawSlideBack(canvas);
//绘制滑动按钮
drawCriBtn(canvas);
}
private void drawSlideBack(Canvas canvas) {
if(deltX <= thumbRadius){
deltX = thumbRadius;
}
if(deltX >= getMeasuredWidth() - thumbRadius){
deltX = getMeasuredWidth() - thumbRadius;
}
mBackSlide = getSlideBackBitmap();
canvas.drawBitmap(mBackSlide, 0, 0, null);
}
private void drawCriBtn(Canvas canvas) {
if(deltX <= thumbRadius){
deltX = thumbRadius;
}
if(deltX >= getMeasuredWidth() - thumbRadius){
deltX = getMeasuredWidth() - thumbRadius;
}
Bitmap bitmap = isTouch ? mCriPre : mCriNor;
int clipX = (int) (lastLength - (deltX - thumbRadius));
Rect src = new Rect(clipX, 0, getMeasuredWidth() + clipX, bitmap.getHeight());
canvas.drawBitmap(bitmap, src, dst, null);
Log.e(TAG, "draw cri btn: deltX = " + deltX);
}
private Bitmap getSlideBackBitmap(){
mPaint.setXfermode(mode);
Bitmap bitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Config.ARGB_8888);
Canvas c = new Canvas(bitmap);
int clipX = (int) (lastLength - (deltX - thumbRadius));
Rect src = new Rect(clipX, 0, getMeasuredWidth() + clipX, mBackLong.getHeight());
c.drawBitmap(mBackLong, src, dst, null);
c.drawBitmap(mBackBlack, 0, 0, mPaint);
mPaint.setXfermode(null);
return bitmap;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
deltX = event.getX();
isTouch = true;
if(mAnimator != null && mAnimator.isRunning()){
return false;
}
break;
case MotionEvent.ACTION_MOVE:
deltX = event.getX();
isTouch = true;
break;
case MotionEvent.ACTION_UP:
deltX = event.getX();
isTouch = false;
switchState();
break;
default:
break;
}
Log.e(TAG, "deltX = " + deltX);
invalidate();
return true;
}
private void switchState() {
if(deltX >0 && deltX <= getMeasuredWidth()/2){//去左边
isOpen = false;
anim(deltX, 0);
}else if(deltX > getMeasuredWidth()/2 && deltX < getMeasuredWidth()){//去右边
isOpen = true;
anim(deltX, getMeasuredWidth());
}else if(deltX <= 0){
isOpen = false;
handleChange();
}else if(deltX >= getMeasuredHeight()){
isOpen = true;
handleChange();
}
}
private void anim(float beginX,float endX){
mAnimator = ValueAnimator.ofFloat(beginX,endX);
mAnimator.setDuration((long)(Math.abs(beginX - endX)*5));
mAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
deltX = (Float) animation.getAnimatedValue();
invalidate();
}
});
mAnimator.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
handleChange();
}
@Override
public void onAnimationCancel(Animator animation) {
}
});
mAnimator.start();
}
private void handleChange(){
if(listener != null && isOpen != cacheIsOpen){
cacheIsOpen = isOpen;
listener.onChange(SwitchButton.this, cacheIsOpen);
}
}
OnSwitchChangeListener listener;
public void setOnSwitChangeListener(OnSwitchChangeListener listener){
this.listener = listener;
}
public interface OnSwitchChangeListener{
void onChange(SwitchButton switchBtn,boolean isOpen);
}
}