ios一些控件還是挺美麗的,可是對android程序猿來說可能比較苦逼,由於ios一些看起來簡單的效果對android來說可能就沒那么簡單了,可是沒辦法非常多產品都是拿ios的一些控件叫android開發者來照着做,今天就來做一個設置中常見的開關效果,
思路:
1:准備二張圖片 一個是包括開和關二種狀態的圖片,一個是上面滑動的button圖片
2:這些圖片肯定是不能通過原生態的控件顯示上去的,要通過canvas畫上去
3:要解決點擊和滑動的事件沖突,由於點擊包括 按下 離開,而滑動包括按下 移動 離開,
以下看代碼邏輯首先是布局文件,非常easy
<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" > <com.example.toggle.ui.MyToggleView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" /> </RelativeLayout>MyToggleView.java 自己定義的控件
package com.example.toggle.ui; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import com.example.toggle.R; /** * 一個view從創建到顯示要經歷的過程 * 1:構造函數 實例初始化 * 2:測量 onMeasure * 3:假設當前view是ViewGroup 還要義務測量它孩子(子view) * 4:指定控件的大小和位置 (onLayout) * 假設當前view是ViewGroup 還要義務指定它孩子的大小和位置(子view) * 5:繪制(就是畫出來再屏幕上可見)onDraw(Canvas canvas) * @author Administrator * * 點擊事件包括點擊 和 離開 而這個離開剛好和移動中的up事件一樣 * */ public class MyToggleView extends View implements View.OnClickListener { private static final String TAG = "MyToggleView"; Paint paint ; private Bitmap bg_bitmap; private Bitmap sliding_bitmap; private float slidingLeft = 0; private int slideLeftMax; /** * 自己定義樣式用它 * @param context * @param attrs * @param defStyleAttr */ public MyToggleView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } /** * 在布局時候用它 * @param context * @param attrs */ public MyToggleView(Context context, AttributeSet attrs) { super(context, attrs); initView(); } private void initView() { paint = new Paint(); bg_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.switch_background); sliding_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.slide_button); slideLeftMax = bg_bitmap.getWidth() - sliding_bitmap.getWidth(); setOnClickListener(this); } /** * 在代碼new的時候用它 * @param context */ public MyToggleView(Context context) { super(context); } /** * 測量 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { /** * 這是父類去測量子view的大小 而我們能夠不要父類去測量 */ // super.onMeasure(bg_bitmap.getWidth(), bg_bitmap.getHeight()); /** * 人為指定控件測量大小 (就是說沒有測量) */ setMeasuredDimension(bg_bitmap.getWidth(), bg_bitmap.getHeight()); } @Override protected void onDraw(Canvas canvas) { canvas.drawBitmap(bg_bitmap, 0, 0, paint); canvas.drawBitmap(sliding_bitmap, slidingLeft , 0, paint); } private boolean isOpened = false; /** * isClickenble為true表示點擊事件生效 但觸摸事件無效 * isClickenble 為false表示點擊事件失效 觸摸事件有效 */ private boolean isClickenble = false; @Override public void onClick(View v) { if(isClickenble){ isOpened = !isOpened; if(isOpened){ slidingLeft = bg_bitmap.getWidth()-sliding_bitmap.getWidth(); }else{ slidingLeft = 0; } invalidate(); } } private float startX = 0;//手指剛觸動時候的x軸坐標 private float lastX = 0;//手指剛觸動時候的x軸坐標 @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event);//運行父類的方法 switch (event.getAction()) {//推斷滑動的動作 是剛按下 還是拖動 還是手指 抬起 case MotionEvent.ACTION_DOWN : lastX = startX = event.getX();//這是距離 這個控件的x軸坐標值 isClickenble = true; break; case MotionEvent.ACTION_MOVE : float endX = event.getX(); int distanceX = (int) Math.abs(endX - lastX); if(distanceX > 5){ isClickenble = false; } refreshView(endX); startX = event.getX();//又一次計算初始值 break; case MotionEvent.ACTION_UP : if(slidingLeft>slideLeftMax/2){ //開 isOpened = true; slidingLeft = slideLeftMax; }else{//關 isOpened = false; slidingLeft = 0; } invalidate(); break; } return true;//表示自己處理 不須要調用父類的方法 } private void refreshView(float endX) { float distance = (endX - startX) ; slidingLeft+=distance; if(slidingLeft<0){ slidingLeft = 0; } if(slidingLeft>slideLeftMax){ slidingLeft = slideLeftMax; } invalidate(); } }
效果圖: