话不多说!直接先看效果图:
在这里我们实现了滑动的的左右滑动(防止其超出边界,在滑动的距离过程中,有个自动选择的效果,并配备文字说明)
首先我们必须知道:
view绘制的流程:onMeasure()测量—>onLayout()布局—->onDraw()绘制—->onTouch()事件
代码如下:
1,新建一个类继承于view,并在布局文件中引入该自定义类
public class SlideButton extends View {
private Bitmap mBitmap_bg;
private Bitmap mBitmap_btn;
private Paint mPaint;
private int mMRight;
public SlideButton(Context context) {
super(context);
}
public SlideButton(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
private void initView() {
//获取图片资源
mBitmap_bg = BitmapFactory.decodeResource(getResources(), R.drawable.background);
mBitmap_btn = BitmapFactory.decodeResource(getResources(), R.drawable.slide_button);
mPaint = new Paint();
mPaint.setAntiAlias(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//测量背景资源的尺寸
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
switch (widthMode) {
case MeasureSpec.AT_MOST:
widthSize = mBitmap_bg.getWidth();
break;
}
switch (heightMode) {
case MeasureSpec.AT_MOST:
heightSize = mBitmap_bg.getHeight();
break;
}
//重新测量其尺寸大小
setMeasuredDimension(widthSize, heightSize);
}
//触摸事件
private float mStartX;
private float mStartY;
private float mChangedemotion;
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
mStartX = event.getRawX();
mStartY = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
float newX = event.getRawX();
float newY = event.getRawY();
//偏移量
float dx = newX - mStartX;
//移动
mChangedemotion += dx;
//从新赋值
mStartX = newX;
mStartY = newY;
break;
case MotionEvent.ACTION_UP://抬起
//在抬起的时候,判断,其划动的的时候在那一边,自动跳转到那一边
//获得总体距离的一半
int sum = mBitmap_bg.getWidth() / 2;
//获得滑动的距离和控件距离的一半
float everything = mBitmap_btn.getWidth() / 2 + mChangedemotion;
if (everything >= sum) {
//跳到最右边,偏移量的改变
mChangedemotion = mMRight;
if (mListener != null) {
mListener.onChange(false);
}
} else {
mChangedemotion = 0;
if (mListener != null) {
mListener.onChange(true);
}
}
break;
}
//重绘--->区别于从新布局requestLayout();
invalidate();
return true;
}
//绘制图片
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap_bg, 0, 0, mPaint);
//过滤掉开关出界的情况
if (mChangedemotion < 0) {
mChangedemotion = 0;
}
//获得滑动的最大的距离
mMRight = mBitmap_bg.getWidth() - mBitmap_btn.getWidth();
if (mChangedemotion > mMRight) {
mChangedemotion = mMRight;
}
canvas.drawBitmap(mBitmap_btn, mChangedemotion, 0, mPaint);
super.onDraw(canvas);
}
private OnStateChangeListenere mListener;
//对外提供一个方法供外部去设置onstateChangeListener接口
public void setOnStategeListener(OnStateChangeListenere listener) {
if (listener != null) {
this.mListener = listener;
}
}
}
2,自定义一个接口
public interface OnStateChangeListenere {
void onChange(boolean isOpen);
}
3,在activity中实现对外提供的方法,即需要回调其接口方法
public class MainActivity extends Activity {
private SlideButton mSilede;
private TextView mTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mSilede = (SlideButton) findViewById(slide);
mTv = (TextView)findViewById(R.id.tv);
mSilede.setOnStategeListener(new OnStateChangeListenere() {
@Override
public void onChange(boolean isOpen) {
//因为使用了接口,此处修改了后(变更为图片或其他的),原实现逻辑代码可以不用修改
mTv.setText(isOpen ?"开启":"关闭");
}
});
}
}