SwitchButton可以點(diǎn)擊的時候切換狀態(tài),類似CheckBox
在拖動的時候,也可以根據(jù)拖動的距離判斷是否切換狀態(tài),類似ToggleButton
因此要區(qū)別出單擊事件和拖動事件
實(shí)現(xiàn)效果如圖所示:
自定義的SwitchButton如下:
public class SwitchButton extends View implements View.OnTouchListener { private Bitmap bg_on, bg_off, slipper_btn; /** * 按下時的x和當(dāng)前的x */ private float downX, nowX; /** * 記錄用戶是否在滑動 */ private boolean onSlip = false; /** * 當(dāng)前的狀態(tài) */ private boolean nowStatus = false; /** * 監(jiān)聽接口 */ private OnChangedListener listener; /** * 一個滑動的距離臨界值,判斷是滑動還是點(diǎn)擊 * getScaledTouchSlop(): * Distance in pixels a touch can wander before we think the user is scrolling * */ private int mTouchSlop=new ViewConfiguration().getScaledTouchSlop(); public SwitchButton(Context context) { super(context); init(); } public SwitchButton(Context context, AttributeSet attrs) { super(context, attrs); init(); } public void init(){ //載入圖片資源 bg_on = BitmapFactory.decodeResource(getResources(), R.mipmap.switch_on_on); bg_off = BitmapFactory.decodeResource(getResources(), R.mipmap.switch_off_off); slipper_btn = BitmapFactory.decodeResource(getResources(), R.mipmap.switch_ball_ball); setOnTouchListener(this); } protected void onDraw(Canvas canvas) { super.onDraw(canvas); Matrix matrix = new Matrix(); Paint paint = new Paint(); float x = 0; //根據(jù)nowX設(shè)置背景,開或者關(guān)狀態(tài) if (nowX < (bg_on.getWidth()/2)){ canvas.drawBitmap(bg_off, matrix, paint);//畫出關(guān)閉時的背景 }else{ canvas.drawBitmap(bg_on, matrix, paint);//畫出打開時的背景 } if (onSlip) {//是否是在滑動狀態(tài), if(nowX >= bg_on.getWidth())//是否劃出指定范圍,不能讓滑塊跑到外頭,必須做這個判斷 x = bg_on.getWidth() - slipper_btn.getWidth()/2;//減去滑塊1/2的長度 else x = nowX - slipper_btn.getWidth()/2; }else { if(nowStatus){//根據(jù)當(dāng)前的狀態(tài)設(shè)置滑塊的x值 x = bg_on.getWidth() - slipper_btn.getWidth(); }else{ x = 0; } } //對滑塊滑動進(jìn)行異常處理,不能讓滑塊出界 if (x < 0 ){ x = 0; } else if(x > bg_on.getWidth() - slipper_btn.getWidth()){ x = bg_on.getWidth() - slipper_btn.getWidth(); } //畫出滑塊 canvas.drawBitmap(slipper_btn, x, 0, paint); } @Override public boolean onTouch(View v, MotionEvent event) { switch(event.getAction()){ case MotionEvent.ACTION_DOWN:{ if (event.getX() > bg_off.getWidth() || event.getY() > bg_off.getHeight()){ return false; }else{ onSlip = true; downX = event.getX(); nowX = downX; } break; } case MotionEvent.ACTION_MOVE:{ nowX = event.getX(); break; } case MotionEvent.ACTION_UP:{ DebugLog.e("mTouchSlop:"+mTouchSlop); onSlip = false; nowX = event.getX(); float float_distance=nowX - downX; int int_disatnce=(int)float_distance; DebugLog.e("int_disatnce:"+int_disatnce); /** * 滑動距離太短,認(rèn)定是點(diǎn)擊事件 */ if(Math.abs(int_disatnce)<mTouchSlop){ if(this.isChecked()){ this.setChecked(false); nowX = 0; }else{ this.setChecked(true); nowX = bg_on.getWidth() - slipper_btn.getWidth(); } }else{ /** * 滑動距離足夠,認(rèn)為是滑動事件 */ if(event.getX() >= (bg_on.getWidth()/2)){ nowStatus = true; nowX = bg_on.getWidth() - slipper_btn.getWidth(); }else{ nowStatus = false; nowX = 0; } } if(listener != null){ listener.OnChanged(SwitchButton.this, nowStatus); } break; } } //刷新界面 invalidate(); return true; } /** * 為WiperSwitch設(shè)置一個監(jiān)聽,供外部調(diào)用的方法 * @param listener */ public void setOnChangedListener(OnChangedListener listener){ this.listener = listener; } /** * 設(shè)置滑動開關(guān)的初始狀態(tài),供外部調(diào)用 * @param checked */ public void setChecked(boolean checked){ if(checked){ nowX = bg_off.getWidth(); }else{ nowX = 0; } nowStatus = checked; } public boolean isChecked() { return nowStatus; } /** * 回調(diào)接口 * */ public interface OnChangedListener { public void OnChanged(SwitchButton wiperSwitch, boolean checkState); }}布局文件中使用:
<com.uestcneon.chuji.changjianglife.share.SwitchButton android:id="@+id/user_privacy_state" android:layout_width="wrap_content" android:layout_height="20dp" android:layout_marginLeft="30dp" />
控件用到的3個資源圖片:
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。
新聞熱點(diǎn)
疑難解答