这里接着上一篇文章 通过NestedScrolling实现RecyclerView拖拽回弹效果,做了一些优化并增加滑动动画效果。
首先看下我们要实现的效果:
功能很简单,需要给RecyclerView做两个扩展:
一、增加拖拽功能
拖拽功能在上一章已经做了介绍,但有几点需要注意:
1、拖拽范围限制
@Override
public void scrollTo(int x, int y) {
if (x < 0) {
x = 0;
} else if (x > maxWidth * 2) {
x = maxWidth * 2;
}
super.scrollTo(x, y);
}
2、惯性问题:当RecyclerView在界面之内交给它自己惯性滑动
@Override
public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
// 当RecyclerView在界面之内交给它自己惯性滑动
return getScrollX() != maxWidth;
}
3、快速左右连续滑动会出现错位问题,需要要限制处理
@Override
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
...
// 限制错位问题
if (dx > 0 && getScrollX() > maxWidth && !ViewCompat.canScrollHorizontally(target, -1)) {
scrollTo(maxWidth, 0);
}
if (dx < 0 && getScrollX() < maxWidth && !ViewCompat.canScrollHorizontally(target, 1)) {
scrollTo(maxWidth, 0);
}
}
4、动画问题:和惯性同样判断什么时候开启动画
@Override
public void onStopNestedScroll(View target) {
mParentHelper.onStopNestedScroll(target);
// 如果不在RecyclerView滑动范围内
if(maxWidth != getScrollX()){
startAnimation(new ProgressAnimation());
}
}
5、多点触控问题:在动画执行时期不处理事件
@Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
return target instanceof RecyclerView && !isRunAnim;
}
mChildView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// 保证动画状态中 子view不能滑动
return isRunAnim;
}
});
二、根据拖拽距离绘制椭圆
1、首先要保证查看更多按钮一直在最右边显示
有两个思路:
(1)自定义扩展得View宽度固定,查看更多按钮位置随着滑动距离变化。
(2)自定义扩展的View宽度随着滑动距离变化,查看更多按钮右居中显示。
2、滑动显示出更多按钮后,开始绘制椭圆。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPath.reset();
float marginTop = (mHeight - mLayoutHeight) / 2;
// 右上角x坐标、右上角y坐标
mPath.moveTo(mMove - mLayoutWidth, marginTop);
// 左边弧形x坐标、左边弧形y坐标、右下角x坐标、右下角y坐标
mPath.quadTo(0, mHeight / 2, mMove - mLayoutWidth, mLayoutHeight + marginTop);
canvas.drawPath(mPath, mBackPaint);
}
demo地址:https://github.com/eatdefecat/DZStickyNavLayout
最后还有个问题很困扰我,如果没有给RecyclerView中itemView设置可以点击,onStartNestedScroll会执行2次,并且onNestedPreScroll方法里返回的dx或者dy会变得很大,实现不了阻力效果。如果有知道这是什么原因引起的欢迎在文章下面留言。