1. 程式人生 > >自定義滑動開關按鈕-SwitchButton

自定義滑動開關按鈕-SwitchButton

最近,在專案開發中需要用到開關按鈕,因為業務需求,需要適應自己的App style,所以決定親自實操一遍,自定義一個控制元件。
業務需求:
    1.開關點選事件
    2.開關滑動事件
    3.涉及了動態測量繪製文字的寬高
先上效果圖,如下:

這裡寫圖片描述

因為比較簡單,沒有自定義屬性,註釋比較完整,所以貼上完整程式碼給你們參考,有問題可以私聊。

完整程式碼如下:

public class AutoButton extends View implements View.OnTouchListener{
    //開關背景圖
    private Bitmap bgBitmap;
    //開關按鈕圖
private Bitmap btnBitmap; private Paint paint; //標記開關滑動的值 private int leftDis=0; //標記開關滑動的最大值 private int slidingMax; //設定開關對應的文字 private final String text1="開"; private final String text2="關; //標記開關狀態 private boolean mCurrent; //標記點選事件 private boolean isClickable; //標記滑動事件 private boolean isMove; //開關開啟的事件監聽器 private SoftFloorListener softFloorListener; //開關關閉的事件監聽器 private HydropowerListener hydropowerListener; //標記開關文字的寬度 float width1,width2; //記錄文字中心點 cx1:繪製文字1的x座標 cx2:繪製文字2的x座標 //cy記錄繪製文字的高度 float cx1,cy,cx2; //程式碼例項化需要的方法 public AutoButton(Context context) { this(context,null); } //在xml佈局時需要用到的方法 public AutoButton(Context context, AttributeSet attrs) { this(context, attrs,0); } public AutoButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(); } //初始化資料 private void initView() { //載入背景圖 bgBitmap= BitmapFactory.decodeResource(getResources(), R.drawable.bg_switchbutton); //載入開關按鈕圖 btnBitmap=BitmapFactory.decodeResource(getResources(),R.drawable.btn_switchbutton); paint=new Paint(); slidingMax=bgBitmap.getWidth()-btnBitmap.getWidth(); paint.setTextSize(35); //測量繪製文字1的寬度 width1= paint.measureText(text1); //測量文字的寬度 Paint.FontMetricsInt fontMetricsInt=paint.getFontMetricsInt(); cy=btnBitmap.getHeight()/2+(fontMetricsInt.descent-fontMetricsInt.ascent)/2; width2= paint.measureText(text2); cx2=(bgBitmap.getWidth()*2-btnBitmap.getWidth())/2-width2/2; paint.setAntiAlias(true); setOnTouchListener(this); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //根據載入圖片設定控制元件的大小 setMeasuredDimension(bgBitmap.getWidth(),bgBitmap.getHeight()); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //繪製背景圖 canvas.drawBitmap(bgBitmap,0,0,paint); //繪製按鈕圖 canvas.drawBitmap(btnBitmap,leftDis,0,paint); //根據不同狀態繪製不同顏色,不同位置的文字 if (mCurrent){ paint.setColor(Color.WHITE); canvas.drawText(text2,cx2,cy,paint); paint.setColor(Color.BLACK); canvas.drawText(text1,cx1,cy,paint); }else { paint.setColor(Color.WHITE); canvas.drawText(text1,cx1,cy,paint); paint.setColor(Color.BLACK); canvas.drawText(text2,cx2,cy,paint); } } //根據事件重新整理檢視 private void flushView() { mCurrent=!mCurrent; if (mCurrent){ leftDis=slidingMax; if (hydropowerListener!=null){ //按鈕開啟監聽器 hydropowerListener.hydropower(); } }else { leftDis=0; if (softFloorListener!=null){ //按鈕關閉監聽器 softFloorListener.softFloor(); } } invalidate(); } //startX 標記手指按下的X座標, lastX 標記移動後的x座標 //disX 標記x方向移動的距離 float startX,lastX,disX; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: isClickable=true; startX=event.getX(); isMove=false; break; case MotionEvent.ACTION_MOVE: lastX=event.getX(); disX=lastX-startX; //設定一個移動的閾值 if (Math.abs(disX)<5) break; isMove=true; isClickable=false; moveBtn(); startX=event.getX(); break; case MotionEvent.ACTION_UP: //點選事件 if (isClickable){ flushView(); } //滑動事件 if (isMove){ if (leftDis>slidingMax/2){ mCurrent=false; }else { mCurrent=true; } flushView(); } break; } return true; } //按鈕滑動時的位置控制 private void moveBtn() { leftDis+=disX; if (leftDis>slidingMax){ leftDis=slidingMax; }else if (leftDis<0){ leftDis=0; } invalidate(); } //設定按鈕開啟監聽器 public void setSoftFloorListener(SoftFloorListener softFloorListener){ this.softFloorListener=softFloorListener; } //設定按鈕關閉監聽器 public void setHydropowerListener(HydropowerListener hydropowerListener){ this.hydropowerListener=hydropowerListener; } //設定按鈕開啟監聽器介面 public interface SoftFloorListener{ void softFloor(); } //設定按鈕開啟監聽器介面 public interface HydropowerListener{ void hydropower(); } }