欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Recyclerview ItemDecoration 通用分割线

程序员文章站 2024-01-16 16:18:59
public class CommonDividerItemDecoration extends RecyclerView.ItemDecoration { public final static int HORIZONTAL = LinearLayoutManager.HORIZONTAL; public final static int VERTICAL = LinearLayoutManager.VERTICAL; public final static float ....

目前还没有试验瀑布流 只写了list 和 grid 待完善

public class CommonDividerItemDecoration extends RecyclerView.ItemDecoration {


    public final static int HORIZONTAL = LinearLayoutManager.HORIZONTAL;

    public final static int VERTICAL = LinearLayoutManager.VERTICAL;

    public final static float DEFAULT_SPACE = 0.5f;

    private Context mContext;
    private int mOrientation;
    private int mRectSpace;
    private int mLeftEdgeSpace;
    private int mTopEdgeSpace;
    private int mRightEdgeSpace;
    private int mBottomEdgeSpace;
    private boolean isIncludeLeft;
    private boolean isIncludeTop;
    private boolean isIncludeRight;
    private boolean isIncludeBottom;
    private Paint mPaint;
    private int mPaintColor;
    private int mMaxSpanGroupIndex;

    private CommonDividerItemDecoration(Builder builder) {
        this.mContext = builder.context;
        this.mOrientation = builder.orientation;
        this.mRectSpace = builder.rectSpace;
        this.mLeftEdgeSpace = builder.leftEdgeSpace;
        this.mTopEdgeSpace = builder.topEdgeSpace;
        this.mRightEdgeSpace = builder.rightEdgeSpace;
        this.mBottomEdgeSpace = builder.bottomEdgeSpace;
        this.isIncludeLeft = builder.isIncludeLeft;
        this.isIncludeTop = builder.isIncludeTop;
        this.isIncludeRight = builder.isIncludeRight;
        this.isIncludeBottom = builder.isIncludeBottom;
        this.mPaintColor = builder.paintColor;
        init();
    }

    private void init() {
        this.mPaint = new Paint();
        this.mPaint.setAntiAlias(true);
        this.mPaint.setStyle(Paint.Style.FILL);
        this.mPaint.setColor(this.mPaintColor);
    }

    @Override
    public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        int childCount = Objects.requireNonNull(parent.getAdapter()).getItemCount();
        if (childCount == 0) return;
        int position = parent.getChildAdapterPosition(view);
        view.setTag(position);
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
            GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();
            int spanCount = gridLayoutManager.getSpanCount();
            mMaxSpanGroupIndex = spanSizeLookup.getSpanGroupIndex(parent.getAdapter().getItemCount() - 1, spanCount);
            if (isFirsColumn(position, spanCount)) {
                if (isFirstRow(position, spanCount)) {
                    outRect.set(isIncludeLeft ? mLeftEdgeSpace : 0, isIncludeTop ? mTopEdgeSpace : 0, mRectSpace, mRectSpace);
                } else if (isLastRow(position, spanCount, childCount)) {
                    outRect.set(isIncludeLeft ? mLeftEdgeSpace : 0, 0, mRectSpace, isIncludeBottom ? mBottomEdgeSpace : 0);
                } else {
                    outRect.set(isIncludeLeft ? mLeftEdgeSpace : 0, 0, mRectSpace, mRectSpace);
                }
            } else if (isFirstRow(position, spanCount)) {
                if (isLastColumn(position, spanCount)) {
                    outRect.set(0, isIncludeTop ? mTopEdgeSpace : 0, isIncludeRight ? mRightEdgeSpace : 0, mRectSpace);
                } else {
                    outRect.set(0, isIncludeTop ? mTopEdgeSpace : 0, mRectSpace, mRectSpace);
                }
            } else if (isLastColumn(position, spanCount)) {
                if (isLastRow(position, spanCount, childCount)) {
                    outRect.set(0, 0, isIncludeRight ? mRightEdgeSpace : 0, isIncludeBottom ? mBottomEdgeSpace : 0);
                } else {
                    outRect.set(0, 0, isIncludeRight ? mRightEdgeSpace : 0, mRectSpace);
                }
            } else if (isLastRow(position, spanCount, childCount)) {
                outRect.set(0, 0, mRectSpace, isIncludeBottom ? mBottomEdgeSpace : 0);
            } else {
                outRect.set(0, 0, mRectSpace, mRectSpace);
            }
        } else if (layoutManager instanceof LinearLayoutManager) {
            if (mOrientation == VERTICAL) {
                if (position == 0) {//默认的只有一条数据的话 底部分割线保留 如果需要特殊处理再说
                    outRect.set(isIncludeLeft ? mLeftEdgeSpace : 0, isIncludeTop ? mTopEdgeSpace : 0
                            , isIncludeRight ? mRightEdgeSpace : 0, mRectSpace);
                } else if (position == childCount - 1) {
                    outRect.set(isIncludeLeft ? mLeftEdgeSpace : 0, 0
                            , isIncludeRight ? mRightEdgeSpace : 0, isIncludeBottom ? mBottomEdgeSpace : 0);
                } else {
                    outRect.set(isIncludeLeft ? mLeftEdgeSpace : 0, 0
                            , isIncludeRight ? mRightEdgeSpace : 0, mRectSpace);
                }
            } else {
                if (position == 0) {
                    outRect.set(isIncludeLeft ? mLeftEdgeSpace : 0, isIncludeTop ? mTopEdgeSpace : 0
                            , mRectSpace, isIncludeBottom ? mBottomEdgeSpace : 0);
                } else if (position == childCount - 1) {
                    outRect.set(0, isIncludeTop ? mTopEdgeSpace : 0
                            , isIncludeRight ? mRightEdgeSpace : 0, isIncludeBottom ? mBottomEdgeSpace : 0);
                } else {
                    outRect.set(0, isIncludeTop ? mTopEdgeSpace : 0
                            , mRectSpace, isIncludeBottom ? mBottomEdgeSpace : 0);
                }
            }
        } else {
            if (mOrientation == VERTICAL) {

            } else {

            }
        }
    }

    @Override
    public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        super.onDraw(c, parent, state);
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            drawGridSpace(c, parent);
        } else if (layoutManager instanceof LinearLayoutManager) {
            if (mOrientation == VERTICAL) {
                drawListVertical(c, parent);
            } else {
                drawListHorizontal(c, parent);
            }
        } else {
            //TODO
        }
    }

    private void drawListVertical(Canvas c, RecyclerView parent) {
        final int childCount = parent.getChildCount();
        final int itemCount = Objects.requireNonNull(parent.getAdapter()).getItemCount();
        if (childCount == 0) return;

        final int left = isIncludeLeft ? parent.getPaddingLeft() + mLeftEdgeSpace : parent.getPaddingLeft();
        final int right = isIncludeRight ? parent.getWidth() - parent.getPaddingRight() - mRightEdgeSpace : parent.getWidth() - parent.getPaddingRight();

        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
            int position = parent.getChildLayoutPosition(child);
            if (position == 0) {
                if (isIncludeTop) {
                    final int top = child.getTop() - params.topMargin - mTopEdgeSpace;
                    final int bottom = top + mTopEdgeSpace;
                    c.drawRect(left, top, right, bottom, mPaint);
                }
                final int top = child.getBottom() + params.bottomMargin;
                final int bottom = top + mRectSpace;
                c.drawRect(left, top, right, bottom, mPaint);
            } else if (position == itemCount - 1) {
                if (isIncludeBottom) {
                    final int top = child.getBottom() + params.bottomMargin;
                    final int bottom = top + mBottomEdgeSpace;
                    c.drawRect(left, top, right, bottom, mPaint);
                }
            } else {
                final int top = child.getBottom() + params.bottomMargin;
                final int bottom = top + mRectSpace;
                c.drawRect(left, top, right, bottom, mPaint);
            }
        }
        drawLeftOrRightSpace(c, parent);
    }

    public void drawLeftOrRightSpace(Canvas c, RecyclerView parent) {
        if (isIncludeLeft) {
            final int left = parent.getPaddingLeft();
            final int top = parent.getPaddingTop();
            final int right = left + mLeftEdgeSpace;
            final int bottom = parent.getHeight() - parent.getPaddingBottom();
            c.drawRect(left, top, right, bottom, mPaint);
        }
        if (isIncludeRight) {
            final int left = parent.getWidth() - parent.getPaddingRight() - mRightEdgeSpace;
            final int top = parent.getPaddingTop();
            final int right = left + mRightEdgeSpace;
            final int bottom = parent.getHeight() - parent.getPaddingBottom();
            c.drawRect(left, top, right, bottom, mPaint);
        }
    }

    private void drawListHorizontal(Canvas c, RecyclerView parent) {
        final int childCount = parent.getChildCount();
        int itemCount = Objects.requireNonNull(parent.getAdapter()).getItemCount();
        if (childCount == 0) return;

        final int top = isIncludeTop ? parent.getPaddingTop() + mTopEdgeSpace : parent.getPaddingTop();
        final int bottom = isIncludeBottom ? parent.getHeight() - parent.getPaddingBottom() - mBottomEdgeSpace : parent.getHeight() - parent.getPaddingBottom();

        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
            int position = parent.getChildLayoutPosition(child);
            if (position == 0) {
                if (isIncludeLeft) {
                    final int left = child.getLeft() - params.leftMargin - mLeftEdgeSpace;
                    final int right = left + mLeftEdgeSpace;
                    c.drawRect(left, top, right, bottom, mPaint);
                }
                final int left = child.getRight() + params.rightMargin;
                final int right = left + mRectSpace;
                c.drawRect(left, top, right, bottom, mPaint);
            } else if (position == itemCount - 1) {
                if (isIncludeRight) {
                    final int left = child.getRight() + params.rightMargin;
                    final int right = left + mRightEdgeSpace;
                    c.drawRect(left, top, right, bottom, mPaint);
                }
            } else {
                final int left = child.getRight() + params.rightMargin;
                final int right = left + mRectSpace;
                c.drawRect(left, top, right, bottom, mPaint);
            }
        }
        drawTopOrBottomSpace(c, parent);
    }

    private void drawTopOrBottomSpace(Canvas c, RecyclerView parent) {
        if (isIncludeTop) {
            final int left = parent.getPaddingLeft();
            final int top = parent.getPaddingTop();
            final int right = parent.getWidth() - parent.getPaddingRight();
            final int bottom = top + mTopEdgeSpace;
            c.drawRect(left, top, right, bottom, mPaint);
        }
        if (isIncludeBottom) {
            final int left = parent.getPaddingLeft();
            final int top = parent.getHeight() - parent.getPaddingBottom() - mBottomEdgeSpace;
            final int right = parent.getWidth() - parent.getPaddingRight();
            final int bottom = top + mBottomEdgeSpace;
            c.drawRect(left, top, right, bottom, mPaint);
        }
    }

    private void drawGridSpace(Canvas canvas, RecyclerView parent) {
        GridLayoutManager gridLayoutManager = (GridLayoutManager) parent.getLayoutManager();
        int spanCount = Objects.requireNonNull(gridLayoutManager).getSpanCount();
        GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();
        int childCount = parent.getChildCount();
        int top, bottom, left, right;
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);
            int position = parent.getChildLayoutPosition(child);
            RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();

            int spanGroupIndex = spanSizeLookup.getSpanGroupIndex(position, spanCount);
            int spanSize = spanSizeLookup.getSpanSize(position);
            int spanIndex = spanSizeLookup.getSpanIndex(position, spanCount);
            // 画bottom分割线,如果没到达底部,绘制bottom
            top = child.getBottom() + layoutParams.bottomMargin;
            bottom = top + mRectSpace;
            left = child.getLeft() - layoutParams.leftMargin;
            right = child.getRight() + layoutParams.rightMargin + mRectSpace;
            canvas.drawRect(left, top, right, bottom, mPaint);
            // 画right分割线
            top = child.getTop() - layoutParams.topMargin;
            bottom = child.getBottom() + layoutParams.bottomMargin;
            left = child.getRight() + layoutParams.rightMargin;
            right = left + mRectSpace;
            canvas.drawRect(left, top, right, bottom, mPaint);
        }

        drawLeftOrRightSpace(canvas, parent);
        drawTopOrBottomSpace(canvas, parent);
    }

    public static class Builder {
        private Context context;
        private int orientation = VERTICAL;
        private int rectSpace;
        private int leftEdgeSpace;
        private int topEdgeSpace;
        private int rightEdgeSpace;
        private int bottomEdgeSpace;
        private boolean isIncludeLeft;
        private boolean isIncludeTop;
        private boolean isIncludeRight;
        private boolean isIncludeBottom;
        private int paintColor = Constants.COLOR.WHITE_SMOKE;

        public Builder(Context context) {
            this.context = context;
            rectSpace = DpUtils.dip2px(context, DEFAULT_SPACE);
            leftEdgeSpace = topEdgeSpace = rightEdgeSpace = bottomEdgeSpace = rectSpace;
        }

        public Context getContext() {
            return context;
        }

        public Builder setContext(Context mContext) {
            this.context = mContext;
            return this;
        }

        public int getOrientation() {
            return orientation;
        }

        public Builder setOrientation(int orientation) {
            this.orientation = orientation;
            return this;
        }

        public int getRectSpace() {
            return rectSpace;
        }

        public Builder setRectSpace(float rectSpace) {
            this.rectSpace = DpUtils.dip2px(context, rectSpace);
            return this;
        }

        public int getLeftEdgeSpace() {
            return leftEdgeSpace;
        }

        public Builder setLeftEdgeSpace(int leftEdgeSpace) {
            this.leftEdgeSpace = DpUtils.dip2px(context, leftEdgeSpace);
            return this;
        }

        public int getTopEdgeSpace() {
            return topEdgeSpace;
        }

        public Builder setTopEdgeSpace(int topEdgeSpace) {
            this.topEdgeSpace = DpUtils.dip2px(context, topEdgeSpace);
            return this;
        }

        public int getRightEdgeSpace() {
            return rightEdgeSpace;
        }

        public Builder setRightEdgeSpace(int rightEdgeSpace) {
            this.rightEdgeSpace = DpUtils.dip2px(context, rightEdgeSpace);
            return this;
        }

        public int getBottomEdgeSpace() {
            return bottomEdgeSpace;
        }

        public Builder setBottomEdgeSpace(int bottomEdgeSpace) {
            this.bottomEdgeSpace = DpUtils.dip2px(context, bottomEdgeSpace);
            return this;
        }

        public boolean isIncludeLeft() {
            return isIncludeLeft;
        }

        public Builder setIncludeLeft(boolean includeLeft) {
            this.isIncludeLeft = includeLeft;
            return this;
        }

        public boolean isIncludeTop() {
            return isIncludeTop;
        }

        public Builder setIncludeTop(boolean includeTop) {
            this.isIncludeTop = includeTop;
            return this;
        }

        public boolean isIncludeRight() {
            return isIncludeRight;
        }

        public Builder setIncludeRight(boolean includeRight) {
            this.isIncludeRight = includeRight;
            return this;
        }

        public boolean isIncludeBottom() {
            return isIncludeBottom;
        }

        public Builder setIncludeBottom(boolean includeBottom) {
            this.isIncludeBottom = includeBottom;
            return this;
        }

        public int getPaintColor() {
            return paintColor;
        }

        public Builder setPaintColor(int paintColor) {
            this.paintColor = paintColor;
            return this;
        }

        public CommonDividerItemDecoration build() {
            return new CommonDividerItemDecoration(this);
        }
    }

    /**
     * 判断是不是第一行
     *
     * @param pos       item index in adapter
     * @param spanCount your grid spanCount
     * @return true or false
     */
    private boolean isFirstRow(int pos, int spanCount) {
        return (pos / spanCount) == 0;
    }

    /**
     * 判断是不是最后一行
     *
     * @param pos        item index in adapter
     * @param spanCount  your grid spanCount
     * @param childCount your total ItemCount
     * @return true or false
     */
    private boolean isLastRow(int pos, int spanCount, int childCount) {
        int ranger = childCount % spanCount;
        if (ranger == 0) {
            ranger = spanCount;
        }
        childCount = childCount - ranger;
        return pos >= childCount;
    }

    /**
     * 判断是不是第一列
     *
     * @param pos       item index in adapter
     * @param spanCount your grid spanCount
     * @return true or false
     */
    private boolean isFirsColumn(int pos, int spanCount) {
        return pos % spanCount == 0;
    }

    /**
     * 判断是不是最后一列
     *
     * @param pos       item index in adapter
     * @param spanCount your grid spanCount
     * @return true or false
     */
    private boolean isLastColumn(int pos, int spanCount) {
        return (pos + 1) % spanCount == 0;
    }
}

本文地址:https://blog.csdn.net/xielunyan666/article/details/107908480

相关标签: Android 分割线