Android自定義控件仿iOS滑塊SwitchButton
SwitchButton可以點(diǎn)擊的時(shí)候切換狀態(tài),類似CheckBox
在拖動(dòng)的時(shí)候,也可以根據(jù)拖動(dòng)的距離判斷是否切換狀態(tài),類似ToggleButton
因此要區(qū)別出單擊事件和拖動(dòng)事件
實(shí)現(xiàn)效果如圖所示:
自定義的SwitchButton如下:
public class SwitchButton extends View implements View.OnTouchListener { private Bitmap bg_on, bg_off, slipper_btn; /** * 按下時(shí)的x和當(dāng)前的x */ private float downX, nowX; /** * 記錄用戶是否在滑動(dòng) */ private boolean onSlip = false; /** * 當(dāng)前的狀態(tài) */ private boolean nowStatus = false; /** * 監(jiān)聽接口 */ private OnChangedListener listener; /** * 一個(gè)滑動(dòng)的距離臨界值,判斷是滑動(dòng)還是點(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)閉時(shí)的背景 }else{ canvas.drawBitmap(bg_on, matrix, paint);//畫出打開時(shí)的背景 } if (onSlip) {//是否是在滑動(dòng)狀態(tài), if(nowX >= bg_on.getWidth())//是否劃出指定范圍,不能讓滑塊跑到外頭,必須做這個(gè)判斷 x = bg_on.getWidth() - slipper_btn.getWidth()/2;//減去滑塊1/2的長(zhǎng)度 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; } } //對(duì)滑塊滑動(dòng)進(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); /** * 滑動(dòng)距離太短,認(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{ /** * 滑動(dòng)距離足夠,認(rèn)為是滑動(dòng)事件 */ 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è)置一個(gè)監(jiān)聽,供外部調(diào)用的方法 * @param listener */ public void setOnChangedListener(OnChangedListener listener){ this.listener = listener; } /** * 設(shè)置滑動(dòng)開關(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個(gè)資源圖片:
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
25個(gè)實(shí)用酷炫的Android開源UI框架
本文為大家分享了25個(gè)實(shí)用酷炫的Android開源UI框架,靈活運(yùn)用這些UI框架可在日常工作中節(jié)省不少時(shí)間2018-04-04Android Studio 修改類的默認(rèn)注釋圖文教程
這篇文章主要介紹了Android Studio 修改類的默認(rèn)注釋圖文教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-03-03Android使用Sensor感應(yīng)器獲取用戶移動(dòng)方向(指南針原理)
這篇文章主要介紹了Android使用Sensor感應(yīng)器獲取用戶移動(dòng)方向的方法,實(shí)例分析了指南針原理極其應(yīng)用,需要的朋友可以參考下2015-12-12GridView實(shí)現(xiàn)桌面圖標(biāo)顯示案例
這篇文章主要為大家詳細(xì)介紹了GridView實(shí)現(xiàn)桌面圖標(biāo)顯示案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08詳解Android SpannableString多行圖文混排的應(yīng)用實(shí)戰(zhàn)
本篇文章主要介紹了Android SpannableString多行圖文混排的應(yīng)用實(shí)戰(zhàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12Android自定義view實(shí)現(xiàn)有header和footer作為layout使用的滾動(dòng)控件
這篇文章主要介紹了Android自定義view實(shí)現(xiàn)有header和footer的滾動(dòng)控件,可以在XML中當(dāng)Layout使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-11-11Navigation?Bundle實(shí)現(xiàn)兩個(gè)Fragment參數(shù)傳遞
這篇文章主要為大家介紹了Navigation?Bundle實(shí)現(xiàn)兩個(gè)Fragment參數(shù)傳遞,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04Android App開發(fā)中ViewPager組件的入門使用教程
這篇文章主要介紹了Android App開發(fā)中ViewPager組件的入門使用教程,ViewPager主要用來實(shí)現(xiàn)通過滑動(dòng)來切換頁面的效果,需要的朋友可以參考下2016-03-03