package com.talent.allshare.widget.switchbutton; import com.youplayer.player.R; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.ViewConfiguration; import android.view.ViewParent; import android.widget.CheckBox; public class SwitchButton extends CheckBox { private Paint mPaint; private ViewParent mParent; private Bitmap bottom; private Bitmap btn; private Bitmap btn_pressed; private Bitmap btn_unpressed; private Bitmap frame; private Bitmap mask; private float downY; private float downX; private float realPos; private float btnPos; private float btnOnPos; private float btnOffPos; private final float offsetY = 0; private float maskWidth; private float maskHeight; private float btnWidth; private float btnInitPos; private int mClickTimeout; private int mTouchSlop; private int mAlpha = 255; private boolean mChecked = false; private boolean mBroadcasting; private boolean doTurnOnAni; private PerformClick mPerformClick; private OnCheckedChangeListener mOnCheckedChangeListener; private OnCheckedChangeListener mOnCheckedChangeWidgetListener; private SetCheckedHandler setCheckedHandler = new SetCheckedHandler(); public SwitchButton(Context context, AttributeSet attrs) { this(context, attrs, android.R.attr.checkboxStyle); } public SwitchButton(Context context) { this(context, null); } public SwitchButton(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initView(context); } private void initView(Context context) { mPaint = new Paint(); mPaint.setColor(Color.WHITE); Resources resources = context.getResources(); // get viewConfiguration mClickTimeout = ViewConfiguration.getPressedStateDuration()+ ViewConfiguration.getTapTimeout(); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); // get Bitmap bottom = BitmapFactory.decodeResource(resources, R.drawable.switch_button_switch); btn_pressed = BitmapFactory.decodeResource(resources,R.drawable.switch_button); btn_unpressed = BitmapFactory.decodeResource(resources,R.drawable.switch_button); frame = BitmapFactory.decodeResource(resources, R.drawable.switch_button_frame); mask = BitmapFactory.decodeResource(resources, R.drawable.switch_button_mask); btn = btn_unpressed; btnWidth = btn_pressed.getWidth(); maskWidth = mask.getWidth(); maskHeight = mask.getHeight(); btnOffPos = btnWidth / 2; btnOnPos = maskWidth - btnWidth / 2; btnPos = mChecked ? btnOnPos : btnOffPos; realPos = getRealPos(btnPos); } @Override public void setEnabled(boolean enabled) { mAlpha = enabled ? 255 : 128; super.setEnabled(enabled); } @Override public boolean isEnabled() { return super.isEnabled(); } public boolean isChecked() { return mChecked; } public void toggle() { setChecked(!mChecked); } private void _setChecked(boolean checked) { int msg = checked ? 1 : 0; setCheckedHandler.sendEmptyMessageDelayed(msg, 10); } public void setChecked(boolean checked) { if (mChecked != checked) { mChecked = checked; btnPos = checked ? btnOnPos : btnOffPos; realPos = getRealPos(btnPos); invalidate(); if (mBroadcasting) { return; } mBroadcasting = true; if (mOnCheckedChangeListener != null) { mOnCheckedChangeListener.onCheckedChanged(SwitchButton.this,mChecked); } if (mOnCheckedChangeWidgetListener != null) { mOnCheckedChangeWidgetListener.onCheckedChanged(SwitchButton.this, mChecked); } mBroadcasting = false; } } private class SetCheckedHandler extends Handler { @Override public void handleMessage(Message msg) { boolean checked = msg.what == 1; if (mChecked != checked) { mChecked = checked; if (mBroadcasting) { return; } mBroadcasting = true; if (mOnCheckedChangeListener != null) { mOnCheckedChangeListener.onCheckedChanged(SwitchButton.this, mChecked); } if (mOnCheckedChangeWidgetListener != null) { mOnCheckedChangeWidgetListener.onCheckedChanged(SwitchButton.this, mChecked); } mBroadcasting = false; } super.handleMessage(msg); } } public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { mOnCheckedChangeListener = listener; } void setOnCheckedChangeWidgetListener(OnCheckedChangeListener listener) { mOnCheckedChangeWidgetListener = listener; } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub int action = event.getAction(); float x = event.getX(); float y = event.getY(); float deltaX = Math.abs(x - downX); float deltaY = Math.abs(y - downY); switch (action) { case MotionEvent.ACTION_DOWN: attemptClaimDrag(); downX = x; downY = y; btn = btn_pressed; btnInitPos = mChecked ? btnOnPos : btnOffPos; break; case MotionEvent.ACTION_MOVE: float time = event.getEventTime() - event.getDownTime(); btnPos = btnInitPos + event.getX() - downX; if (btnPos >= btnOffPos) { btnPos = btnOffPos; } if (btnPos <= btnOnPos) { btnPos = btnOnPos; } doTurnOnAni = btnPos > (btnOffPos - btnOnPos) / 2 + btnOnPos; realPos = getRealPos(btnPos); break; case MotionEvent.ACTION_UP: btn = btn_unpressed; time = event.getEventTime() - event.getDownTime(); if (deltaY < mTouchSlop && deltaX < mTouchSlop && time < mClickTimeout) { if (mPerformClick == null) { mPerformClick = new PerformClick(); } if (!post(mPerformClick)) { performClick(); } } else { btnAnimation.start(!doTurnOnAni); } break; } invalidate(); return isEnabled(); } private final class PerformClick implements Runnable { public void run() { performClick(); } } @Override public boolean performClick() { btnAnimation.start(!mChecked); return true; } /** * Tries to claim the user's drag motion, and requests disallowing any * ancestors from stealing events in the drag. */ private void attemptClaimDrag() { mParent = getParent(); if (mParent != null) { mParent.requestDisallowInterceptTouchEvent(true); } } private float getRealPos(float btnPos) { return btnPos - btnWidth / 2; } @Override protected void onDraw(Canvas canvas) { canvas.saveLayerAlpha( new RectF(0, offsetY, mask.getWidth(), mask.getHeight() + offsetY), mAlpha, 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(mask, 0, offsetY, mPaint); mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(bottom, realPos, offsetY, mPaint); mPaint.setXfermode(null); canvas.drawBitmap(frame, 0, offsetY, mPaint); canvas.drawBitmap(btn, realPos, offsetY, mPaint); canvas.restore(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension((int) maskWidth, (int) (maskHeight + 2 * offsetY)); } // animation private BtnAnimation btnAnimation = new BtnAnimation(); private class BtnAnimation extends IncrementAnimation { private final float INIT_VELOCITY = 400; public void start(boolean doTurnOn) { long now = SystemClock.uptimeMillis(); mAnimationLastTime = now; mAnimatedVelocity = doTurnOn ? -INIT_VELOCITY : INIT_VELOCITY; mAnimationPosition = btnPos; mCurrentAnimationTime = now + ANIMATION_FRAME_DURATION; mAnimating = true; mHandler.removeMessages(MSG_ANIMATE); mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE), mCurrentAnimationTime); } @Override protected void doAnimation() { if (mAnimating) { incrementAnimation(); if (mAnimationPosition <= btnOnPos) { mAnimating = false; mAnimationPosition = btnOnPos; _setChecked(true); } else if (mAnimationPosition >= btnOffPos) { mAnimating = false; mAnimationPosition = btnOffPos; _setChecked(false); } else { mCurrentAnimationTime += ANIMATION_FRAME_DURATION; mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE),mCurrentAnimationTime); } moveView(mAnimationPosition); } } @Override protected void moveView(float position) { btnPos = position; realPos = getRealPos(btnPos); invalidate(); } } }