先写出自定义View界面
代码如下:先创建一个View继承View,然后重写测量方法去测量出要显示的真是高度,再重写绘制方法,去把这个按钮绘制在什么位置。然后就是为我们后续的触摸事件做准备,重写OnTouchEvent()
package com.example.z.selfscrollunlock;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by z on 2017/11/25.
*/
public class SelfUnLockView extends View {
private Bitmap mBitmap;
private int mHeight;
private int mWidth;
private Paint mPaint;
private int mWidth1;
public SelfUnLockView(Context context) {
this(context, null);
}
public SelfUnLockView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.switch_button);
mHeight = mBitmap.getHeight();
mWidth = mBitmap.getWidth();
mPaint = new Paint();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mWidth1 = MeasureSpec.makeMeasureSpec(widthMeasureSpec, MeasureSpec.EXACTLY);
setMeasuredDimension(mWidth1, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
float rawX = event.getRawX();
//当我手指触摸到滑块时候,滑块过来要移动这个点减去滑块一般的长度 raw
float moveX = rawX - mWidth / 2;
scrollTo((int) -moveX,0);
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
break;
}
return super.onTouchEvent(event);
}
}
在自定义View 的构造方法中,我们去初始化一个画笔,初始化背景的 长 宽。在onTouch()中,处理触摸事件,在手指按下的时候,让滑块中间位置移动到触摸点:注意,这个ScrollTo方法,往右边移动是减去一个数,可以想成,水调用这个Scroll方法,是this ,当前自定义View。你简单记忆成这个移动是移动他的爹,滑块向右移动,你就当成是滑块不动,他爹应该是往那边移动才是我们想要的结果,他爹是往左边移动才行。我们的左边是右边正,往左了肯定是负。效果如下:
但是很多问题,比如越界问题,回弹等,我们一步一步处理
处理点击滑块外部不响应
把这个滑动事件判断一下执行:
if (rawX > 0 && rawX < mWidth) {
scrollTo((int) -moveX, 0);
}
处理左边越界问题
更改一个地方:
if (rawX > mWidth/2 && rawX < mWidth) {
处理滑块滑动
在ontouch事件的move 动作中处理:并处理滑动越界问题
case MotionEvent.ACTION_MOVE:
//处理越界问题
float rawXMove = event.getRawX();//
if(rawXMove >mWidth/2 && rawXMove <=getMeasuredWidth()-mWidth/2){
float dexX = rawXMove - mWidth/2; //变化量
scrollTo((int) ( - dexX), 0);
}
break;
注意上面的滑动越界问题,我是通过手指的位置判断的,当然你可以通过一个增加量来判断是否满足条件,如果满足不满足条件直接把偏移量置零或者最大 。注意上面的判断有个细节,我使用的是getMeasuredWidth( ) 来处理,并不是用的mWidth1,如果你是用后者,你会发现这个值非常大。会越界。这里的getMeasuredWidth()拿的值就是控件背景宽度。如果弄不明白就直接使用增加量判断
你的滑块是否能滑动呢?
如果你的滑块能点击,不能滑动,注意看你的自定义控件是否消费事件,如果没有消费事件,就是掉super方法,肯定不会处理,所以你要返回值改为true.消费时间才行,因为滑动事件和点击事件不同的!
滑块的回原点
case MotionEvent.ACTION_UP:
float endRawX = event.getRawX();
if(endRawX
解锁不成功,缓慢回弹
1.创建Scroller对象
2.调用startScroll 方法去滚动 ,配置滚动信息
3.出发重新绘制调用 invalidate();
4.计算滚动的偏移量。重写computerScroll( ) ,根据当前已过时间计算偏移量 返回的是boolean值,如果没结束,就是滚动还没有结束, scroller.scrollTo(X,getcriiX(),0)然后出发绘制,完整代码如下:
package com.example.z.selfscrollunlock;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Scroller;
import android.widget.Toast;
/**
* Created by z on 2017/11/25.
*/
public class SelfUnLockView extends View {
private Bitmap mBitmap;
private int mHeight;
private int mWidth;
private Paint mPaint;
private int mWidth1;
private float mRawX;
private Scroller mScroller;
private ScrollListener mListener;
public SelfUnLockView(Context context) {
this(context, null);
}
public SelfUnLockView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.switch_button);
mHeight = mBitmap.getHeight();
mWidth = mBitmap.getWidth();
mPaint = new Paint();
mScroller = new Scroller(getContext());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mWidth1 = MeasureSpec.makeMeasureSpec(widthMeasureSpec, MeasureSpec.EXACTLY);
setMeasuredDimension(mWidth1, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mRawX = event.getRawX();
//当我手指触摸到滑块时候,滑块过来要移动这个点减去滑块一般的长度 raw
float moveX = mRawX - mWidth / 2;
if (mRawX > mWidth / 2 && mRawX < mWidth) {
scrollTo((int) -moveX, 0);
}
break;
case MotionEvent.ACTION_MOVE:
//处理越界问题
float rawXMove = event.getRawX();//
if(rawXMove >mWidth/2 && rawXMove <=getMeasuredWidth()-mWidth/2){
float dexX = rawXMove - mWidth/2; //变化量
scrollTo((int) ( - dexX), 0);
}
break;
case MotionEvent.ACTION_UP:
float endRawX = event.getRawX();
if(endRawX
测滑菜单
需求分析:
1.继承Viewgroup
2.测量布局孩子
3.处理越界问题
package com.example.z.selfscrollunlock;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by z on 2017/11/25.
*/
public class SlidingMenu extends ViewGroup {
private float mRawX;
private View mRight;
private View mLeft;
private int mMeasuredWidth;
private int mMeasuredWidth1;
public SlidingMenu(Context context) {
this(context, null);
}
public SlidingMenu(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
mLeft = getChildAt(0);
mRight = getChildAt(1);
mMeasuredWidth = mLeft.getMeasuredWidth();
mMeasuredWidth1 = mRight.getMeasuredWidth();
int measuredHeight = mLeft.getMeasuredHeight();
int measuredHeight1 = mRight.getMeasuredHeight();
mLeft.layout(-mMeasuredWidth, 0, 0, measuredHeight);
mRight.layout(0, 0, mMeasuredWidth1, measuredHeight1);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mRawX = event.getRawX();
break;
case MotionEvent.ACTION_MOVE:
float rawX1 = event.getRawX();
float v = -rawX1 + mRawX; //滚动偏移量
float finall = v + getScrollX(); //最终偏移量
if(finall >0){
scrollTo(0,0);
}else {
scrollTo(-mMeasuredWidth,0);
}
return true;
//
// int i = mMeasuredWidth1 - mMeasuredWidth;
// if (v <-i) {
// v = i;
// }
// else if (v < -mMeasuredWidth) {
// v = 0;
// }
//// scrollTo((int) -v, 0);
// scrollBy((int) -v, 0);
// mRawX = rawX1;
}
return true;
}
}