RecyclerView stick头 通过ItemDecoration来实现

46 阅读1分钟

ItemDecoration

当我们调用 RecyclerView 的 addItemDecoration 添加 decoration 的时候,RecyclerView 就会调用该类的 onDraw 方法去绘制分割线,也就是说分割线是绘制出来的;

RecyclerView.ItemDecoration 类是抽象类;

有三个重要的方法
getItemOffsets 当item在界面可见时会被调用
onDraw 默认会调用一次,每次触摸移动都会一直在调用
onDrawOver 默认会调用一次,每次触摸移动都会一直在调用

onDraw

绘制Item的分割线和默认stick头的样式

  1. 遍历当前界面的所有条目
  2. 判断如果是header条目,则draw Stick头,否则draw一个线。
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
{
        if (parent.getAdapter() instanceof StickFragment.NBAStarAdapter) {
            StickFragment.NBAStarAdapter adapter =(StickFragment.NBAStarAdapter) parent.getAdapter();
(parent.getLayoutManager())).findFirstVisibleItemPosition()
            ));
            int count = parent.getChildCount();//获取可见范围内Item的总数
            for (int i = 0; i < count; i++) {
                View view = parent.getChildAt(i);
                int position = parent.getChildLayoutPosition(view);
                boolean isHeader = adapter.isGroupHeader(position);
                int left = parent.getPaddingLeft();
                int right = parent.getWidth() - parent.getPaddingRight();
                if (isHeader) {
                    c.drawRect(left, view.getTop() - mItemHeaderHeight, right, view.getTop(), mItemHeaderPaint);
                    mTextPaint.getTextBounds(adapter.getGroupName(position), 0, adapter.getGroupName(position).length(), mTextRect);
                    c.drawText(adapter.getGroupName(position), left + mTextPaddingLeft, (view.getTop() - mItemHeaderHeight) + mItemHeaderHeight / 2 + mTextRect.height() / 2, mTextPaint);
                } else {
                    c.drawRect(left, view.getTop() - 1, right, view.getTop(), mLinePaint);
                }
            }
        }
    }

onDrawOver

绘制stick头在滑动时的样式

  1. 如果当前没有走到stick的条目样式时,直接return
  2. 如果下一个条目是header类型,则需要把前一个stick条目给缩小(移除掉屏幕)。
  3. 下一个条目不header类型,则保持stick头的样式一直在屏幕最上面一直绘制成最新样式
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
    if (parent.getAdapter() instanceof StickFragment.NBAStarAdapter) {
        StickFragment.NBAStarAdapter adapter = (StickFragment.NBAStarAdapter) parent.getAdapter();
        int position = ((LinearLayoutManager) (parent.getLayoutManager())).findFirstVisibleItemPosition();
        View view = parent.findViewHolderForAdapterPosition(position).itemView;
        boolean isHeader = adapter.isGroupHeader(position + 1);
        int top = parent.getPaddingTop();
        int left = parent.getPaddingLeft();
        int right = parent.getWidth() - parent.getPaddingRight();
        if (adapter.getGroupName(position).isNullOrEmpty()) {
            return
        }
        if (isHeader) {
            int bottom = Math.min(mItemHeaderHeight, view.getBottom());
            c.drawRect(left, top + view.getTop() - mItemHeaderHeight, right, top + bottom, mItemHeaderPaint);
            mTextPaint.getTextBounds(adapter.getGroupName(position), 0, adapter.getGroupName(position).length(), mTextRect);
            c.drawText(adapter.getGroupName(position), left + mTextPaddingLeft, top + mItemHeaderHeight / 2 + mTextRect.height() / 2 - (mItemHeaderHeight - bottom), mTextPaint);
        } else {
            c.drawRect(left, top, right, top + mItemHeaderHeight, mItemHeaderPaint);
            mTextPaint.getTextBounds(adapter.getGroupName(position), 0, adapter.getGroupName(position).length(), mTextRect);
            c.drawText(adapter.getGroupName(position), left + mTextPaddingLeft, top + mItemHeaderHeight / 2 + mTextRect.height() / 2, mTextPaint);
        }
        c.save();
    }

}