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();
}
}
效果圖:

