仿饿了么横向列表滑动释放查看更多

这里接着上一篇文章 通过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会变得很大,实现不了阻力效果。如果有知道这是什么原因引起的欢迎在文章下面留言。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,521评论 25 709
  • 内容抽屉菜单ListViewWebViewSwitchButton按钮点赞按钮进度条TabLayout图标下拉刷新...
    皇小弟阅读 46,994评论 22 665
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 14,216评论 4 61
  • 花叹,叹! 音符写梦 2014-8-15 23:28 刚传完花的照片 心里再次忧伤 一上午 我看到花的含苞 听到花...
    如伊老师阅读 1,891评论 0 1
  • 以前的我脾气不好,一点事不顺心都会发火,同学说我被宠坏了,现在的我学会了隐忍,但还是脾气不好,我不知道是什么造就了...
    Elinery阅读 975评论 0 0