總共有兩張圖片,一張背景圖片,一張遮罩圖片。背景圖片有開關字樣,經過遮住一個字來實現開關按鈕。繼承自View控件,經過Canvas和Paint結合來實現圖片的繪製。html
經過canvas的drawBitmap方法和距離左邊的位置來繪製圖片,調用invalidate方法來不斷的更新UI,就能夠實現滑動的效果。java
public class MyToggleButton extends View implements OnClickListener{ /** * 作爲背景的圖片 */ private Bitmap backgroundBitmap; /** * 能夠滑動的圖片 */ private Bitmap slideBtn; private Paint paint; /** * 滑動按鈕的左邊屆 */ private float slideBtn_left; /** * 當前開關的狀態 * true 爲開 */ private boolean currState = false; /** * 判斷是否發生拖動,若是拖動了,就再也不響應 onclick 事件 */ private boolean isDrag = false; /** * 在代碼裏面建立對象的時候,使用此構造方法 */ public MyToggleButton(Context context) { super(context); } /** * 在佈局文件中聲名的view,建立時由系統自動調用。 * @param context 上下文對象 * @param attrs 屬性集 */ public MyToggleButton(Context context, AttributeSet attrs) { super(context, attrs); initView(); } /** * 初始化 */ private void initView() { //初始化圖片 backgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.switch_background); slideBtn = BitmapFactory.decodeResource(getResources(), R.drawable.slide_button); //初始化 畫筆 paint = new Paint(); paint.setAntiAlias(true); // 打開抗矩齒 //添加onclick事件監聽 setOnClickListener(this); } /* * view 對象顯示的屏幕上,有幾個重要步驟: * 一、構造方法 建立 對象。 * 二、測量view的大小。 onMeasure(int,int); * 三、肯定view的位置 ,view自身有一些建議權,決定權在 父view手中。 onLayout(); * 四、繪製 view 的內容 。 onDraw(Canvas) */ /** * 測量尺寸時的回調方法 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // super.onMeasure(widthMeasureSpec, heightMeasureSpec); /** * 設置當前view的大小 * width :view的寬度 * height :view的高度 (單位:像素) */ try { setMeasuredDimension(backgroundBitmap.getWidth(),backgroundBitmap.getHeight()); } catch (Exception e) { e.printStackTrace(); } } @Override /** * 繪製當前view的內容 */ protected void onDraw(Canvas canvas) { // super.onDraw(canvas); // 繪製 背景 /* * backgroundBitmap 要繪製的圖片 * left 圖片的左邊屆 * top 圖片的上邊屆 * paint 繪製圖片要使用的畫筆 */ canvas.drawBitmap(backgroundBitmap, 0, 0, paint); //繪製 可滑動的按鈕 canvas.drawBitmap(slideBtn, slideBtn_left, 0, paint); } @Override /** * onclick 事件在View.onTouchEvent 中被解析。 * 系統對onclick 事件的解析,過於簡陋,只要有down 事件 up 事件,系統即認爲 發生了click 事件 * */ public void onClick(View v) { if(!isDrag){ //若是沒有拖動,才執行改變狀態的動做 currState = !currState; flushState(); } } /** * down 事件時的x值 */ private int firstX; /** * touch 事件的上一個x值 */ private int lastX; @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: firstX = lastX =(int) event.getX(); isDrag = false; break; case MotionEvent.ACTION_MOVE: //判斷是否發生拖動 if(Math.abs(event.getX()-firstX)>5){ isDrag = true; } //計算 手指在屏幕上移動的距離 int dis = (int) (event.getX() - lastX); //將本次的位置 設置給lastX lastX = (int) event.getX(); //根據手指移動的距離,改變slideBtn_left 的值 slideBtn_left = slideBtn_left+dis; break; case MotionEvent.ACTION_UP: //在發生拖動的狀況下,根據最後的位置,判斷當前開關的狀態 if (isDrag) { int maxLeft = backgroundBitmap.getWidth() - slideBtn.getWidth(); // slideBtn左邊屆最大值 /* * 根據 slideBtn_left 判斷,當前應是什麼狀態 */ if (slideBtn_left > maxLeft / 2) { // 此時應爲 打開的狀態 currState = true; } else { currState = false; } flushState(); } break; } flushView(); return true; } /** * 刷新當前狀態 */ private void flushState() { if(currState){ slideBtn_left = backgroundBitmap.getWidth()-slideBtn.getWidth(); }else{ slideBtn_left = 0; } mToggleSwitch.openOrClose(currState); flushView(); } /** * 刷新當前視力 */ private void flushView() { //對 slideBtn_left 的值進行判斷 ,確保其在合理的位置 即 0<=slideBtn_left <= maxLeft int maxLeft = backgroundBitmap.getWidth()-slideBtn.getWidth(); // slideBtn 左邊屆最大值 //確保 slideBtn_left >= 0 slideBtn_left = (slideBtn_left>0)?slideBtn_left:0; //確保 slideBtn_left <=maxLeft slideBtn_left = (slideBtn_left<maxLeft)?slideBtn_left:maxLeft; /* * 刷新當前視圖 致使 執行onDraw執行 */ invalidate(); } public void setmToggleSwitch(ToggleSwitch mToggleSwitch) { this.mToggleSwitch = mToggleSwitch; } private ToggleSwitch mToggleSwitch; public interface ToggleSwitch { /** * true 爲開 ,false 爲關 * @param open */ public void openOrClose(boolean open); } }
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <com.example.MyToggleButton android:id="@+id/my_toggle_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" /> </RelativeLayout>
myToggleButton = (MyToggleButton) findViewById(R.id.my_toggle_btn); myToggleButton.setmToggleSwitch(new ToggleSwitch() { @Override public void openOrClose(boolean open) { if (open) { Toast.makeText(MainActivity.this, "打開", Toast.LENGTH_SHORT).show(); }else { Toast.makeText(MainActivity.this, "關閉", Toast.LENGTH_SHORT).show(); } } });