UI:SwitchButton,可滑动的button

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);
	}
}


 

你可能感兴趣的:(UI:SwitchButton,可滑动的button)