最近参照网上的一些资料写了一个竖直的 SwitchButton,记录如下:
package com.example.switchbutton;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
public class VerticalSwitchButton extends View {
private final int MAX_ALPHA = 255; // alpha value
private Bitmap mSwitchBottom, mSwitchThumb;
private float mCurrentY = 0;
private boolean mSwitchOn = false; //default off
private int mMoveLength = 0; //the max movable length
private float mLastY = 0; //the first down Y position
private Rect mDest = null; //target draw area
private int mDeltY = 0; //the offset of moving
private Paint mPaint = null;
private OnChangeListener mListener = null;
private boolean mFlag = false;
private int destWidth = 0; //target draw area width
private int destHeight = 0; //target draw area height
private boolean mIsScrolled = false; //whether is scrolling
public VerticalSwitchButton(Context context) {
this(context, null);
// TODO Auto-generated constructor stub
}
public VerticalSwitchButton(Context context, AttributeSet attrs) {
this(context, attrs, 0);
// TODO Auto-generated constructor stub
}
public VerticalSwitchButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init();
}
/**
* Initialize the sources
*/
public void init() {
mSwitchBottom = BitmapFactory.decodeResource(getResources(),
R.drawable.switch_bottom);
mSwitchThumb = BitmapFactory.decodeResource(getResources(),
R.drawable.switch_btn_pressed);
destWidth = mSwitchThumb.getWidth() + 1;
destHeight = mSwitchBottom.getHeight() + 1;
mMoveLength = mSwitchBottom.getHeight() - mSwitchThumb.getHeight();
mDest = new Rect(0, 0, destWidth, destHeight);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setAlpha(MAX_ALPHA);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
setMeasuredDimension(mSwitchThumb.getWidth(), mSwitchBottom.getHeight());
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
float thumbY = 0;
if (mDeltY > 0 || mDeltY == 0 && mSwitchOn) {
thumbY = destHeight - (mSwitchThumb.getHeight());
} else if (mDeltY < 0 || mDeltY == 0 && !mSwitchOn) {
thumbY = 0;
}
canvas.saveLayerAlpha(new RectF(mDest), MAX_ALPHA, Canvas.MATRIX_SAVE_FLAG
| Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
| Canvas.FULL_COLOR_LAYER_SAVE_FLAG
| Canvas.CLIP_TO_LAYER_SAVE_FLAG);
canvas.drawBitmap(mSwitchBottom, ((destWidth / 2) - (mSwitchBottom.getWidth() / 2)), 0, null);
//canvas.drawBitmap(mSwitchThumb, ((destWidth / 2) - (mSwitchThumb.getWidth() / 2)), (destHeight - (mSwitchThumb.getHeight())), null);
canvas.drawBitmap(mSwitchThumb, ((destWidth / 2) - (mSwitchThumb.getWidth() / 2)), thumbY, null);
canvas.restore();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastY = event.getY();
return true;
case MotionEvent.ACTION_MOVE:
mCurrentY = event.getY();
mDeltY = (int) (mCurrentY - mLastY);
//To assess the click event
if (mDeltY > 10 || mDeltY < -10) {
mIsScrolled = true;
}
/*
* No need to do anything, When switch on and deltY > 0,
* or switch off and deltY < 0.
*/
if ((mSwitchOn && mDeltY > 0) || (!mSwitchOn && mDeltY < 0)) {
mFlag = true;
mDeltY = 0;
}
if (Math.abs(mDeltY) > mMoveLength) {
mDeltY = mDeltY > 0 ? mMoveLength : - mMoveLength;
}
invalidate();
break;
case MotionEvent.ACTION_UP:
//Is a click event.
if (!mIsScrolled) {
mDeltY = mSwitchOn ? -mMoveLength : mMoveLength;
mSwitchOn = !mSwitchOn;
if (mListener != null) {
mListener.onChange(this, mSwitchOn);
}
invalidate();
mDeltY = 0;
break;
}
mIsScrolled = false;
if (Math.abs(mDeltY) > 0 && Math.abs(mDeltY) < mMoveLength / 2) {
mDeltY = 0;
invalidate();
return true;
} else if (Math.abs(mDeltY) > mMoveLength / 2) {
mDeltY = mDeltY > 0 ? mMoveLength : -mMoveLength;
mSwitchOn = !mSwitchOn;
if(mListener != null) {
mListener.onChange(this, mSwitchOn);
}
invalidate();
mDeltY = 0;
return true;
} else if (mDeltY == 0 && mFlag) {
mDeltY = 0;
mFlag = false;
return true;
}
return super.onTouchEvent(event);
default:
break;
}
invalidate();
return super.onTouchEvent(event);
}
public void setOnChangeListener(OnChangeListener listener) {
mListener = listener;
}
public interface OnChangeListener {
public void onChange(VerticalSwitchButton sb, boolean state);
}
public void toggle() {
setChecked(!mSwitchOn);
}
public void setChecked(boolean checked) {
mSwitchOn = checked;
if(mListener != null) {
mListener.onChange(this, mSwitchOn);
}
invalidate();
}
}