android 仿ios開關控件


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();
	}
}

效果圖:




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM