美文网首页
从源码分析 RecyclerView 的分割线原理

从源码分析 RecyclerView 的分割线原理

作者: cao苗子 | 来源:发表于2019-08-16 15:32 被阅读0次

    先来看 RecyclerView 中的 measureChild

    从这个方法中开始看:

    public void measureChild(@NonNull View child, int widthUsed, int heightUsed) {
                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
    
                final Rect insets = mRecyclerView.getItemDecorInsetsForChild(child);
                widthUsed += insets.left + insets.right;
                heightUsed += insets.top + insets.bottom;
                final int widthSpec = getChildMeasureSpec(getWidth(), getWidthMode(),
                        getPaddingLeft() + getPaddingRight() + widthUsed, lp.width,
                        canScrollHorizontally());
                final int heightSpec = getChildMeasureSpec(getHeight(), getHeightMode(),
                        getPaddingTop() + getPaddingBottom() + heightUsed, lp.height,
                        canScrollVertically());
                if (shouldMeasureChild(child, widthSpec, heightSpec, lp)) {
                    child.measure(widthSpec, heightSpec);
                }
            }
    

    我们不难发现 final Rect insets = mRecyclerView.getItemDecorInsetsForChild(child);获取子View的 rect 然后再进行设置 rect。
    我们再看里面的内容

     Rect getItemDecorInsetsForChild(View child) {
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            if (!lp.mInsetsDirty) {
                return lp.mDecorInsets;
            }
    
            if (mState.isPreLayout() && (lp.isItemChanged() || lp.isViewInvalid())) {
                // changed/invalid items should not be updated until they are rebound.
                return lp.mDecorInsets;
            }
            final Rect insets = lp.mDecorInsets;
            insets.set(0, 0, 0, 0);
            final int decorCount = mItemDecorations.size();
            for (int i = 0; i < decorCount; i++) {
                mTempRect.set(0, 0, 0, 0);
                mItemDecorations.get(i).getItemOffsets(mTempRect, child, this, mState);
                insets.left += mTempRect.left;
                insets.top += mTempRect.top;
                insets.right += mTempRect.right;
                insets.bottom += mTempRect.bottom;
            }
            lp.mInsetsDirty = false;
            return insets;
        }
    

    在这里面我们只需要关注

    for (int i = 0; i < decorCount; i++) {
                mTempRect.set(0, 0, 0, 0);
                mItemDecorations.get(i).getItemOffsets(mTempRect, child, this, mState);
                insets.left += mTempRect.left;
                insets.top += mTempRect.top;
                insets.right += mTempRect.right;
                insets.bottom += mTempRect.bottom;
            }
    

    遍历所有的item,decorCount就是recyclerView的列表数量,mItemDecorations.get(i)得到item的分割线,然后回调 getItemOffsets()方法,这个时候就会执行RecyclerView.ItemDecoration中的getItemOffsets这个方法,对Rect进行设置。

    接着看RecyclerView 中的 onDraw

    在这里对item进行绘制

     @Override
        public void onDraw(Canvas c) {
            super.onDraw(c);
    
            final int count = mItemDecorations.size();
            for (int i = 0; i < count; i++) {
                mItemDecorations.get(i).onDraw(c, this, mState);
            }
        }
    

    我们看到 mItemDecorations.get(i).onDraw(c, this, mState); 这个和前面的基本一样,只不过这个是回调 onDraw方法也就是 RecyclerView.ItemDecoration 分割线中的onDraw()对分割线进行绘制。

    到这里就分析完了

    相关文章

      网友评论

          本文标题:从源码分析 RecyclerView 的分割线原理

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