美文网首页
PtrClassicFrameLayout配合RecyclerV

PtrClassicFrameLayout配合RecyclerV

作者: 肖霄的潇潇 | 来源:发表于2018-03-29 11:31 被阅读0次

    自己项目中使用ViewPager加Fragment模式,来加载图片列表。每个Fragment中recyclerview使用PtrClassicFrameLayout实现下拉刷新。其中“最近更新”列表无法下拉刷新。


    image.png

    1.PtrClassicFrameLayout通过checkCanDoRefresh方法判断是否可以下拉刷新

    mPtrFrameLayout.setPtrHandler(new PtrHandler() {
                @Override
                public void onRefreshBegin(PtrFrameLayout frame) {
                    mNextBeginId = 0;
                    getMaterialTabList(mNextBeginId, CachePolicy.ONLY_NET);
                }
    
                @Override
                public boolean checkCanDoRefresh(PtrFrameLayout frame, View view, View header) {         
                  return PtrDefaultHandler.checkContentCanBePulledDown(frame, view, header);
                }
            });
    

    checkContentCanBePulledDown的相关实现

    public static boolean canChildScrollUp(View view) {
            if (android.os.Build.VERSION.SDK_INT < 14) {
                if (view instanceof AbsListView) {
                    final AbsListView absListView = (AbsListView) view;
                    return absListView.getChildCount() > 0
                            && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
                            .getTop() < absListView.getPaddingTop());
                } else {
                    return view.getScrollY() > 0;
                }
            } else {
                return view.canScrollVertically(-1);
            }
        }
    
        /**
         * Default implement for check can perform pull to refresh
         *
         * @param frame
         * @param content
         * @param header
         * @return
         */
        public static boolean checkContentCanBePulledDown(PtrFrameLayout frame, View content, View header) {
            return !canChildScrollUp(content);
        }
    

    该项目已不支持14以下版本,决定是否可以拉刷新的方法只有view.canScrollVertically(-1);

    RecyclerView.canScrollVertically(1)的值表示是否能向上滚动,false表示已经滚动到底部
    RecyclerView.canScrollVertically(-1)的值表示是否能向下滚动,false表示已经滚动到顶部
    

    项目中可以正常向下滑动时,RecyclerView.canScrollVertically(-1)返回false,说明RecyclerView已滚动到顶部,不能再向下滚动,此时可以执行下拉刷新。“最近更新”列表无法下拉刷新,RecyclerView.canScrollVertically(-1)返回true。可以继续跟踪源码查找原因。

            public boolean canScrollVertically(int direction) {
    12724        final int offset = computeVerticalScrollOffset();
    12725        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
    12726        if (range == 0) return false;
    12727        if (direction < 0) {
    12728            return offset > 0;
    12729        } else {
    12730            return offset < range - 1;
    12731        }
    12732    }
    
    

    参数direction为-1,canScrollVertically返回true,说明offset > 0,computeVerticalScrollOffset() > 0,RecyclerView重写了computeVerticalScrollOffset方法

        @Override
        public int computeVerticalScrollOffset() {
            if (mLayout == null) {
                return 0;
            }
            return mLayout.canScrollVertically() ? mLayout.computeVerticalScrollOffset(mState) : 0;
        }
    

    这里mLayout是LayoutManager类型,项目中设置了setLayoutManager

    mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(GRID_SPAN_COUNT, StaggeredGridLayoutManager.VERTICAL));
    

    则StaggeredGridLayoutManager的computeVerticalScrollOffset(state)方法如下

        @Override
        public int computeVerticalScrollOffset(RecyclerView.State state) {
            return computeScrollOffset(state);
        }
        private int computeScrollOffset(RecyclerView.State state) {
            if (getChildCount() == 0) {
                return 0;
            }
            return ScrollbarHelper.computeScrollOffset(state, mPrimaryOrientation,
                    findFirstVisibleItemClosestToStart(!mSmoothScrollbarEnabled),
                    findFirstVisibleItemClosestToEnd(!mSmoothScrollbarEnabled),
                    this, mSmoothScrollbarEnabled, mShouldReverseLayout);
        }
    
    ScrollbarHelper.computeScrollOffset方法

    minPosition=1,maxPosition=4,laidOutArea =1920, 说明一屏展示的4张图片Position是从1开始的,而不是0。正常能下拉的RecyclerView的minPosition是从0,开始的,无法下拉刷新的列表头部隐藏了什么呢?

    本项目通过BaseQuickAdapter给RecyclerView添加了头部,mAdapter.addHeaderView(mHeader),但此时mHeader是GONE,说明即使mHeader是GONE的情况下,StaggeredGridLayoutManager的computeVerticalScrollOffset也会将的RecyclerView的头部偏移量计算进来。

    问题解决:
    RecyclerView的头部为GONE时,getChildAt(0)拿到的是列表的第一个item,可以通过getChildAt(0).getTop()值来进行计算


    问题解决

    相关文章

      网友评论

          本文标题:PtrClassicFrameLayout配合RecyclerV

          本文链接:https://www.haomeiwen.com/subject/lrcmcftx.html