功能描述:
实现一个开关,效果如下:
功能分析:
View的行为 :
- click,longClick,
- dispatchTouchEvent():touch分发,android希望用来处理是否分发touch事件
- onInterceptTouchEvent():touch拦截,android希望处理是否拦截touch事件
- 是否拦截孩子touch
- onTouchEvent(): touch处理, android希望开发人员封装触摸行为给用户提供交换
- setOnTouchListener():
View的刷新: invalidate() —> draw() —> onDraw()
- 回调
- setXXXListener设置监听的方法 由提供者创造,用来给 使用者设置监听回调
- 提供者 –> onXXXXListener
- 提供者 –>调用接口中的方法
- 使用者 –>实现接口
代码实现:
- 布局界面:
<?xml version="1.0" encoding="utf-8"?>
<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="com.cdw.switchtoggle.MainActivity">
<com.cdw.switchtoggle.SwitchToggleView
android:id="@+id/stv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
- SwitchToggleView.java:
package com.cdw.switchtoggle;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by dongwei on 2016/7/31.
*/
public class SwitchToggleView extends View {
private Bitmap mSwitchBackground;//背景图片
private Bitmap mSwitchSlide;//滑块图片
private final static int STATE_NONE = 0;
private final static int STATE_DOWN = 1;
private final static int STATE_MOVE = 2;
private final static int STATE_UP = 3;
private boolean isOpened = true;//用来标记滑块是否打开
private int mState = STATE_NONE;//用来标记状态
private float mCurrentX;
private OnSwitchListener mListener;
private Paint mPaint = new Paint();
public SwitchToggleView(Context context) {
this(context, null);
}
public SwitchToggleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 设置背景资源
*
* @param resId
*/
public void setSwitchBackground(int resId) {
mSwitchBackground = BitmapFactory.decodeResource(getResources(), resId);
}
public void setSwichSlide(int resId) {
mSwitchSlide = BitmapFactory.decodeResource(getResources(), resId);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mSwitchBackground != null) {
int width = mSwitchBackground.getWidth();
int height = mSwitchBackground.getHeight();
setMeasuredDimension(width, height);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
@Override
protected void onDraw(Canvas canvas) {
//绘制背景显示
if (mSwitchBackground != null) {
int left = 0;
int top = 0;
canvas.drawBitmap(mSwitchBackground, left, top, mPaint);
}
if (mSwitchSlide == null) {
return;
}
int slideWidth = mSwitchSlide.getWidth();//滑块的宽度
int switchWidth = mSwitchBackground.getWidth();
switch (mState) {
case STATE_DOWN:
case STATE_MOVE:
if (!isOpened) {
//滑块是关闭的
if (mCurrentX < slideWidth / 2f) {
//绘制在左侧
canvas.drawBitmap(mSwitchSlide, 0, 0, mPaint);
} else {
float left = mCurrentX - slideWidth / 2f;
float maxLeft = switchWidth - slideWidth;
if (left > maxLeft) {
left = maxLeft;
}
canvas.drawBitmap(mSwitchSlide, left, 0, mPaint);
}
} else {
//滑块是打开的
float middle = switchWidth - slideWidth / 2f;
if (mCurrentX > middle) {
//绘制为打开
canvas.drawBitmap(mSwitchSlide, switchWidth - slideWidth, 0, mPaint);
} else {
float left = mCurrentX - slideWidth / 2f;
if (left < 0){
left = 0;
}
canvas.drawBitmap(mSwitchSlide, left, 0, mPaint);
}
}
break;
case STATE_UP:
case STATE_NONE:
//绘制滑块
if (!isOpened) {
canvas.drawBitmap(mSwitchSlide, 0, 0, mPaint);
} else {
canvas.drawBitmap(mSwitchSlide, switchWidth - slideWidth, 0, mPaint);
}
break;
default:
break;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mState = STATE_DOWN;
mCurrentX = event.getX();
invalidate();//触发刷新
break;
case MotionEvent.ACTION_MOVE:
mState = STATE_MOVE;
mCurrentX = event.getX();
invalidate();//触发刷新
break;
case MotionEvent.ACTION_UP:
mState = STATE_UP;
invalidate();//触发刷新
//判断状态改变
int switchWidth = mSwitchBackground.getWidth();
mCurrentX = event.getX();
if (switchWidth / 2f > mCurrentX && isOpened){
isOpened = false;
if (mListener != null){
mListener.onSwitchChange(isOpened);
}
}else if (switchWidth / 2f < mCurrentX && !isOpened){
isOpened = true;
if (mListener != null){
mListener.onSwitchChange(isOpened);
}
}
break;
default:
break;
}
//消费touch事件
return true;
}
public void setOnSwitchListener(OnSwitchListener listener){
this.mListener = listener;
}
public interface OnSwitchListener{
//开关状态改变
void onSwitchChange(boolean isOpened);
}
}
- mainActivity.java
package com.cdw.switchtoggle;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends Activity {
private SwitchToggleView mView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mView = (SwitchToggleView) findViewById(R.id.stv);
mView.setSwitchBackground(R.drawable.switch_background);
mView.setSwichSlide(R.drawable.slide_button_background);
mView.setOnSwitchListener(new SwitchToggleView.OnSwitchListener() {
@Override
public void onSwitchChange(boolean isOpened) {
Toast.makeText(getApplicationContext(), isOpened ? "打开" : "关闭", Toast.LENGTH_SHORT).show();
}
});
}
}
项目链接:https://github.com/ChenDongWei/Android/tree/671a45e83d5884d0ffde92fc3dcb5daf5923b250/switchtoggle