美文网首页
一篇文章全面 & 解析RecyclerView.ItemDeco

一篇文章全面 & 解析RecyclerView.ItemDeco

作者: JianLee | 来源:发表于2022-02-16 16:58 被阅读0次

    RecyclerView没有像之前ListView提供divider属性,而是提供了方法

    recyclerView.addItemDecoration()
    

    这时候我们需要去定制自己的ItemDecoration

    ItemDecoration类主要是三个方法:

    public void onDraw(Canvas c, RecyclerView parent, State state)
    public void onDrawOver(Canvas c, RecyclerView parent, State state)
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state)
    
    • 重写getItemOffsets(),可以实现类似padding的效果
    • 重写onDraw,可以实现类似绘制背景的效果,用来绘制分隔线
    • 重写onDrawOver,可以在View上覆盖内容

    padding

    直接传递dp

    class SpaceItemDecoration(
        private var left: Int = 0,
        private var top: Int = 0,
        private var right: Int = 0,
        private var bottom: Int = 0
    ) : RecyclerView.ItemDecoration() {
    
        override fun getItemOffsets(
            outRect: Rect,
            view: View,
            parent: RecyclerView,
            state: RecyclerView.State
        ) {
            super.getItemOffsets(outRect, view, parent, state)
            outRect.left = ScreenUtils.dpToPx(left.toFloat())
            outRect.right = ScreenUtils.dpToPx(right.toFloat())
            outRect.top = ScreenUtils.dpToPx(top.toFloat())
            outRect.bottom = ScreenUtils.dpToPx(bottom.toFloat())
        }
    }
    

    grid列表间隔设置

    class GridSpaceItemDecoration(@Px val space: Int) : RecyclerView.ItemDecoration() {
    
        override fun getItemOffsets(
            outRect: Rect,
            view: View,
            parent: RecyclerView,
            state: RecyclerView.State
        ) {
            super.getItemOffsets(outRect, view, parent, state)
            if (parent.layoutManager is GridLayoutManager) {
                val spanCount = (parent.layoutManager as GridLayoutManager?)?.spanCount ?: return
                val layoutParams = view.layoutParams as GridLayoutManager.LayoutParams
                outRect.top = space / 2
                outRect.bottom = space / 2
                when (layoutParams.spanIndex) {
                    0 -> {
                        //第一列左边全部 右边一半
                        outRect.left = space
                        outRect.right = space / 2
                    }
                    spanCount - 1 -> {
                        //最后一列左边一半右边全部
                        outRect.left = space / 2
                        outRect.right = space
                    }
                    else -> {
                        //中间列 左右各一半
                        outRect.right = space / 2
                        outRect.left = space / 2
                    }
                }
            }
        }
    
    }
    

    分割线

    要实现分割线效果需要 getItemOffsets()和 onDraw()2个方法,首先用 getItemOffsets给item下方空出一定高度的空间(例子中是1dp),然后用onDraw绘制这个空间

    public class SimpleDividerDecoration extends RecyclerView.ItemDecoration {
    
        private int dividerHeight;
        private Paint dividerPaint;
    
        public SimpleDividerDecoration(Context context) {
            dividerPaint = new Paint();
            dividerPaint.setColor(context.getResources().getColor(R.color.colorAccent));
            dividerHeight = context.getResources().getDimensionPixelSize(R.dimen.divider_height);
        }
    
    
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            super.getItemOffsets(outRect, view, parent, state);
            outRect.bottom = dividerHeight;
        }
    
        @Override
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
            int childCount = parent.getChildCount();
            int left = parent.getPaddingLeft();
            int right = parent.getWidth() - parent.getPaddingRight();
    
            for (int i = 0; i < childCount - 1; i++) {
                View view = parent.getChildAt(i);
                float top = view.getBottom();
                float bottom = view.getBottom() + dividerHeight;
                c.drawRect(left, top, right, bottom, dividerPaint);
            }
        }
    }
    

    标签

    使用onDrawOver()来实现“推荐”,”热卖“,“秒杀“

    public class LeftAndRightTagDecoration extends RecyclerView.ItemDecoration {
        private int tagWidth;
        private Paint leftPaint;
        private Paint rightPaint;
    
        public LeftAndRightTagDecoration(Context context) {
            leftPaint = new Paint();
            leftPaint.setColor(context.getResources().getColor(R.color.colorAccent));
            rightPaint = new Paint();
            rightPaint.setColor(context.getResources().getColor(R.color.colorPrimary));
            tagWidth = context.getResources().getDimensionPixelSize(R.dimen.tag_width);
        }
    
        @Override
        public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
            super.onDrawOver(c, parent, state);
            int childCount = parent.getChildCount();
            for (int i = 0; i < childCount; i++) {
                View child = parent.getChildAt(i);
                int pos = parent.getChildAdapterPosition(child);
                boolean isLeft = pos % 2 == 0;
                if (isLeft) {
                    float left = child.getLeft();
                    float right = left + tagWidth;
                    float top = child.getTop();
                    float bottom = child.getBottom();
                    c.drawRect(left, top, right, bottom, leftPaint);
                } else {
                    float right = child.getRight();
                    float left = right - tagWidth;
                    float top = child.getTop();
                    float bottom = child.getBottom();
                    c.drawRect(left, top, right, bottom, rightPaint);
    
                }
            }
        }
    }
    

    分组、StickyHeader

       @Override
        public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
            super.onDrawOver(c, parent, state);
            int itemCount = state.getItemCount();
            int childCount = parent.getChildCount();
            int left = parent.getPaddingLeft();
            int right = parent.getWidth() - parent.getPaddingRight();
            float lineHeight = textPaint.getTextSize() + fontMetrics.descent;
    
            long preGroupId, groupId = -1;
            for (int i = 0; i < childCount; i++) {
                View view = parent.getChildAt(i);
                int position = parent.getChildAdapterPosition(view);
    
                preGroupId = groupId;
                groupId = callback.getGroupId(position);
                if (groupId < 0 || groupId == preGroupId) continue;
    
                String textLine = callback.getGroupFirstLine(position).toUpperCase();
                if (TextUtils.isEmpty(textLine)) continue;
    
                int viewBottom = view.getBottom();
                float textY = Math.max(topGap, view.getTop());
                if (position + 1 < itemCount) { //下一个和当前不一样移动当前
                    long nextGroupId = callback.getGroupId(position + 1);
                    if (nextGroupId != groupId && viewBottom < textY ) {//组内最后一个view进入了header
                        textY = viewBottom;
                    }
                }
                c.drawRect(left, textY - topGap, right, textY, paint);
                c.drawText(textLine, left, textY, textPaint);
            }
    
        }
    

    自定义的功能就结束了,详细可了解RecyclerView之ItemDecoration由浅入深

    相关文章

      网友评论

          本文标题:一篇文章全面 & 解析RecyclerView.ItemDeco

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