一.概述
为了满足recycleview数据过多时,能够快速滑动到指定位置,特意自定义了一个控件,用来实现该功能,先看下效果图:
二.创建一个SlideBar类继承View
1.重写onMeasue方法:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMySize(MeasureSpec.getSize(widthMeasureSpec), widthMeasureSpec);
int height = getMySize(MeasureSpec.getSize(heightMeasureSpec), heightMeasureSpec);
//设置控件的大小
setMeasuredDimension(width, height);
}
private int getMySize(int defaultSize, int measureSpec) {
int mySize = defaultSize;
int mode = MeasureSpec.getMode(measureSpec);
int size = MeasureSpec.getSize(measureSpec);
switch (mode) {
case MeasureSpec.UNSPECIFIED: {//如果没有指定大小,就设置为默认大小
mySize = defaultSize;
break;
}
case MeasureSpec.AT_MOST: {//如果测量模式是最大取值为size
//我们将大小取最大值,你也可以取其他值
mySize = size;
break;
}
case MeasureSpec.EXACTLY: {//如果是固定的大小,那就不要去改变它
mySize = size;
break;
}
}
return mySize;
}
自定义控件继承view一般都需要重写onMeasuer方法,这个方法目的就是测量控件的大小而已.
2.重写onDraw方法:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//加载拖拽图片
Bitmap bitmap =BitmapFactory.decodeResource(getResources(), R.mipmap.title_scroll_n);
//分别得到图片的宽,高
int height = bitmap.getHeight();
mWidth = bitmap.getWidth();
//记录宽,高中的较大值用来滑动的时候判断
mSlideBarHeight = height > mWidth ? height : mWidth;
//将图片画出来
canvas.drawBitmap(bitmap,getMeasuredWidth()- mWidth,0,mPaint);
}
ondraw方法主要就是滑出我们的view需要显示的内容,我们这里就只要显示拖拽图片即可.
3.重写onTouchEvent(MotionEvent event)方法:
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//记录按下的x,y坐标
float downX = event.getX();
mDownY = event.getY();
//如果按下的位置不是拖拽图片就不响应事件
if (downX > getMeasuredWidth() || downX < getMeasuredWidth()- mWidth|| mDownY > Math.abs(getScrollY()) + mSlideBarHeight
|| mDownY < Math.abs(getScrollY())) {
return false;
}
break;
case MotionEvent.ACTION_MOVE:
//计算滑动的距离的百分百
float diffY = move(event);
//滑动拖拽图片
scrollBy(0, -(int) diffY);
mDownY = event.getY();
break;
case MotionEvent.ACTION_UP:
move(event);
break;
case MotionEvent.ACTION_OUTSIDE:
move(event);
break;
}
return true;
}
private float move(MotionEvent event) {
float diffY = event.getY() - mDownY;
//判断界限
if (getScrollY() - diffY > 0) {
diffY = getScrollY();
}
if (getScrollY() - diffY < -(getMeasuredHeight()-mSlideBarHeight)) {
diffY = getScrollY() + getMeasuredHeight()-mSlideBarHeight;
}
//已经滑动的距离
int scrollHeight = getScrollY() - (int) diffY;
//求出滑动的距离占View的高度的百分比
float progress = Math.abs(scrollHeight)*1.0f / (getMeasuredHeight()-mSlideBarHeight);
//使得返回的position的范围在0~size之间
if (progress >= 0 && progress <= 1) {
//计算已经滑动的距离,应该时recycleview滑动到的位置
int position = (int) Math.ceil(progress * size);
if (mOnTouchingChangedListener != null) {
mOnTouchingChangedListener.onTouchingChanged(position);
}
}
return diffY;
}
重写onTouchevent方法主要是做2件事,一是让拖拽图片滑动,而是计算已经滑动的距离,应该时recycleview滑动到的位置,然后回调给使用者,然后将recycleview滑动到指定的位置.