美文网首页
PinnedHeaderItemDecoration修复

PinnedHeaderItemDecoration修复

作者: boboyuwu | 来源:发表于2017-09-15 11:09 被阅读26次

    1.0.4
    修复添加Header后Pinned吸顶闪动一下问题

    原因:
    由于在代码中获取PinnedView下方的View的position代码这样实现的

        /**
         * @param c
         * @param parent
         * @param state
         */
        @Override
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
            createPinnedHeader(parent);
    
            if (mPinnedHeaderView != null) {
                // check overlap section view.
                //TODO support only vertical header currently.
                final int headerEndAt = mPinnedHeaderView.getTop() + mPinnedHeaderView.getHeight() + 1;
                final View v = parent.findChildViewUnder(c.getWidth() / 2, headerEndAt);
                if (isPinnedView(parent, v)) {
                    mPinnedHeaderTop = v.getTop() - mPinnedHeaderView.getHeight();
                } else {
                    mPinnedHeaderTop = 0;
                }
    
                if (isHeaderView(mFirstVisiblePosition)) {
                    return;
                }
                mClipBounds = c.getClipBounds();
                mClipBounds.top = mPinnedHeaderTop + mPinnedHeaderView.getHeight();
                c.clipRect(mClipBounds);
    
            }
        }
    
    

    在isPinnedView(parent, v)方法里增加了这段操作

        private boolean isPinnedView(RecyclerView parent, View v) {
            final int position = parent.getChildAdapterPosition(v) - mBuilder.mStickProvider.getHeaderCount();
            if (position == RecyclerView.NO_POSITION) {
                return false;
            }
            final int viewType = mBuilder.mStickProvider.getItemViewType(position);
    
            return isPinnedViewType(viewType);
        }
    

    那么问题出在这,假设我们添加了2个Header

    12345678.png

    效果图是这样的,我在activity中获取itemtype这样操作的

       @Override
            public int getItemViewType(int position) {
                if(position<headers.size()){
                    return SimpleBean.TYPE_HEADER+position;
                }
                int realPosition=position-headers.size();
                SimpleBean simpleBean = mList.get(realPosition);
                return simpleBean.getType();
            }
    

    一般网上框架也是这么操作的,封装的Adapter都会将position-(header总长度)然后传递给自己的Adapter

    3214214214.png

    而我滑动到这个位置时

    final int headerEndAt = mPinnedHeaderView.getTop() + mPinnedHeaderView.getHeight() + 1;
    final View v = parent.findChildViewUnder(c.getWidth() / 2, headerEndAt);
    final int position = parent.getChildAdapterPosition(v) - mBuilder.mStickProvider.getHeaderCount();
    

    此时这个v所在的position等于4,也就是 i=2 的position
    而我们减去header后就等于2然后传递给了我们自己的Adapter,用来获取itemtype
    ok,这样导致的问题在于我们自己的Adapter又拿这个2-header总长度,然后就等于0了,
    等于0时这个Type返回的getItemViewType等于true

    这样就会走上面源码中的if

     if (isPinnedView(parent, v)) {
                    mPinnedHeaderTop = v.getTop() - mPinnedHeaderView.getHeight();
                }
    

    所以mPinnedHeaderTop 此时就不等于0了,在下面onDrawOver中就会根据mPinnedHeaderTop 这个值垂直移动canvas,造成了顶部的pinned向上滑动也就是闪动那个问题,而继续滑动到i==2刚好消失时,这个时候传给我们Adapter的position又等于3了,我们减去header总长度后等于1,所以这个时候getItemViewType返回false,就会走上面源码中的else,这样mPinnedHeaderTop 为0,onDrawOver中移动canvas也为0,等于不移动,所以滑动到这个位置时pinned又消失回来了.

    else {
       mPinnedHeaderTop = 0;
        }
    
    
        @Override
        public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
            if (mPinnedHeaderView != null && !isHeaderView(mFirstVisiblePosition)) {
                c.save();
                mClipBounds.top = 0;
                c.clipRect(mClipBounds, Region.Op.UNION);
                c.translate(0, mPinnedHeaderTop);
                mPinnedHeaderView.draw(c);
    
                c.restore();
            }
        }
    

    这个问题分析清楚就好解决啦,把- mBuilder.mStickProvider.getHeaderCount();这段去掉就好了

    相关文章

      网友评论

          本文标题:PinnedHeaderItemDecoration修复

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