package com.example.compoundbuttonview.view; import com.example.compoundbuttonview.R; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuff.Mode; 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 SlideSwitchView extends View{ /** Switch底部樣式圖片 */ private Bitmap mSwitchBottom; /** Switch 當前樣式 */ private Bitmap mSwitchThumb; /** Switch無操做狀況下的樣式 */ private Bitmap mSwitchThumbNormal; /** Switch當前手指觸摸式的樣式 */ private Bitmap mSwitchThumbPressed; /** Switch 框架 */ private Bitmap mSwitchFrame; private Bitmap mSwitchMask; private float mCurrentX = 0; /** Switch 開關狀態,默認是 開:true */ private boolean mSwitchOn = true; /** Switch 最大移動距離 */ private int mMoveLength; /** 第一次按下的有效區域 */ private float mLastX = 0; /** 繪製的目標區域大小 */ private Rect mDest = null; /** 截取源圖片的大小 */ private Rect mSrc = null; /** Switch 移動的偏移量 */ private int mMoveDeltX = 0; /** 畫筆工具 */ private Paint mPaint = null; /** Switch 狀態監聽接口 */ private OnSwitchChangedListener switchListener = null; private boolean mFlag = false; /** enabled 屬性 爲 true */ private boolean mEnabled = true; /** 最大透明度,就是不透明 */ private final int MAX_ALPHA = 255; /** 當前透明度,這裏主要用於若是控件的enable屬性爲false時候設置半透明 ,即不能夠點擊 */ private int mAlpha = MAX_ALPHA; /** Switch 判斷是否在拖動 */ private boolean mIsScrolled =false; public SlideSwitchView(Context context) { this(context, null); } public SlideSwitchView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SlideSwitchView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } /** * 初始化相關資源 */ public void init() { mSwitchThumbPressed = BitmapFactory.decodeResource(getResources(),R.drawable.checkswitch_btn_pressed); mSwitchThumbNormal = BitmapFactory.decodeResource(getResources(),R.drawable.checkswitch_btn_unpressed); mSwitchBottom = BitmapFactory.decodeResource(getResources(),R.drawable.checkswitch_bottom); mSwitchFrame = BitmapFactory.decodeResource(getResources(),R.drawable.checkswitch_frame); mSwitchMask = BitmapFactory.decodeResource(getResources(),R.drawable.checkswitch_mask); mSwitchThumb = mSwitchThumbNormal; mMoveLength = mSwitchBottom.getWidth() - mSwitchFrame.getWidth(); //繪製區域大小 mDest = new Rect(0, 0, mSwitchFrame.getWidth(),mSwitchFrame.getHeight()); mSrc = new Rect(); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setAlpha(255); //mPaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN)); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub setMeasuredDimension(mSwitchFrame.getWidth(), mSwitchFrame.getHeight()); } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); if (mMoveDeltX > 0 || mMoveDeltX == 0 && mSwitchOn) { if (mSrc != null) { mSrc.set(mMoveLength - mMoveDeltX, 0, mSwitchBottom.getWidth() - mMoveDeltX, mSwitchFrame.getHeight()); } } else if (mMoveDeltX < 0 || mMoveDeltX == 0 && !mSwitchOn) { if (mSrc != null) { mSrc.set(-mMoveDeltX, 0, mSwitchFrame.getWidth() - mMoveDeltX, mSwitchFrame.getHeight()); } } Log.d("mAlpha", "mAlpha:" + mAlpha); //繪製一個不透明矩形 爲白色 和黑色底襯 成灰色 canvas.saveLayerAlpha(new RectF(mDest), 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(mSwitchBottom, mSrc, mDest, null); canvas.drawBitmap(mSwitchThumb, mSrc, mDest, null); canvas.drawBitmap(mSwitchFrame, 0, 0, null); canvas.drawBitmap(mSwitchMask, 0, 0, mPaint); canvas.restore(); } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub //若是Enabled屬性設定爲true,觸摸效果纔有效 if(!mEnabled){ return true; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mSwitchThumb = mSwitchThumbPressed; mLastX = event.getX(); break; case MotionEvent.ACTION_MOVE: mCurrentX = event.getX(); mMoveDeltX = (int) (mCurrentX - mLastX); if(mMoveDeltX > 10){ //設置了10這個偏差距離,能夠更好的實現點擊效果 mIsScrolled = true; } // 若是開關開着向左滑動,或者開關關着向右滑動(這時候是不須要處理的) if ((mSwitchOn && mMoveDeltX < 0) || (!mSwitchOn && mMoveDeltX > 0)) { mFlag = true; mMoveDeltX = 0; } if (Math.abs(mMoveDeltX) > mMoveLength) { mMoveDeltX = mMoveDeltX > 0 ? mMoveLength : -mMoveLength; } invalidate(); break; case MotionEvent.ACTION_UP: mSwitchThumb = mSwitchThumbNormal; //若是沒有滑動過,就看做一次點擊事件 if(!mIsScrolled){ mMoveDeltX = mSwitchOn ? mMoveLength : -mMoveLength; mSwitchOn = !mSwitchOn; if (switchListener != null) { switchListener.onSwitchChange(this, mSwitchOn); } invalidate(); mMoveDeltX = 0; break; } mIsScrolled = false; if (Math.abs(mMoveDeltX) > 0 && Math.abs(mMoveDeltX) < mMoveLength / 2) { mMoveDeltX = 0; invalidate(); } else if (Math.abs(mMoveDeltX) > mMoveLength / 2 && Math.abs(mMoveDeltX) <= mMoveLength) { mMoveDeltX = mMoveDeltX > 0 ? mMoveLength : -mMoveLength; mSwitchOn = !mSwitchOn; if (switchListener != null) { switchListener.onSwitchChange(this, mSwitchOn); } invalidate(); mMoveDeltX = 0; } else if (mMoveDeltX == 0 && mFlag) { // 這時候獲得的是不須要進行處理的,由於已經move過了 mMoveDeltX = 0; mFlag = false; } default: break; } invalidate(); return true; } /** * 設置 switch 狀態監聽 * */ public void setOnChangeListener(OnSwitchChangedListener listener) { switchListener = listener; } /** * switch 開關監聽接口 * */ public interface OnSwitchChangedListener{ public void onSwitchChange(SlideSwitchView switchView, boolean isChecked); } @Override public void setEnabled(boolean enabled) { // TODO Auto-generated method stub mEnabled = enabled; mAlpha = enabled ? MAX_ALPHA : MAX_ALPHA/2; Log.d("enabled",enabled ? "true": "false"); super.setEnabled(enabled); invalidate(); } /** 自動判斷切換至相反的屬性 : true -->false ;false -->true */ public void toggle() { setChecked(!mSwitchOn); } /** 設置選中的狀態(選中:true 非選中: false) */ public void setChecked(boolean checked) { mSwitchOn = checked; invalidate(); } }