优雅 RecyclerView 万能分割线 2.0

效果

在这里插入图片描述

三个demo

  1. 垂直列表
  2. 水平列表
  3. Grid

全量代码,一个类


import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;
import android.widget.LinearLayout;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.util.Objects;

/**
 * TODO StaggeredGridLayoutManager
 */
public class MyDividerItemDecoration extends RecyclerView.ItemDecoration {

    private final int ONE_SPAN_COUNT = 1;//list VERTICAL 垂直列表
    private final int NO_SPAN_COUNT = 0;//list HORIZONTAL 水平列表

    private Paint mPaint;
    private int lineWidth = 2;
    private boolean drawOuterBorder = false;
    private boolean hasTitle = false;
    private String colorString = "#eeeeee";

    public MyDividerItemDecoration() {
        setColorString(colorString);
    }

    public MyDividerItemDecoration(int lineWidth, boolean drawOuterBorder, String colorString, boolean hasTitle) {
        this.lineWidth = lineWidth;
        this.drawOuterBorder = drawOuterBorder;
        //this.colorString = colorString;
        this.hasTitle = hasTitle;
        setColorString(colorString);
    }

    @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();
        int position = parent.getChildAdapterPosition(view);
        RecyclerView.LayoutManager manager = parent.getLayoutManager();
        int left = 0, top = 0, right = 0, bottom = 0, spanCount = 0;
        if (manager instanceof GridLayoutManager) {
            spanCount = ((GridLayoutManager)manager).getSpanCount();
        } else if (manager instanceof LinearLayoutManager) {
            int orientation = ((LinearLayoutManager)manager).getOrientation();
            spanCount = orientation == LinearLayout.VERTICAL ? ONE_SPAN_COUNT : NO_SPAN_COUNT;
        } else {

        }
        left = needDrawLeft(position, spanCount, childCount) ? lineWidth : 0;
        top = needDrawTop(position, spanCount, childCount) ? lineWidth : 0;
        right = needDrawRight(position, spanCount, childCount) ? lineWidth : 0;
        bottom = needDrawBottom(position, spanCount, childCount) ? lineWidth : 0;
        outRect.set(left, top, right, bottom);
    }

    @Override
    public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        super.onDraw(c, parent, state);
        RecyclerView.LayoutManager manager = parent.getLayoutManager();
        if (manager instanceof GridLayoutManager) {
            drawGrid(c, parent);
        } else if (manager instanceof LinearLayoutManager) {
            drawLinear(c, parent);
        } else {

        }
    }

    private void drawLinear(Canvas c, RecyclerView parent) {
        LinearLayoutManager manager = (LinearLayoutManager) parent.getLayoutManager();
        int orientation = manager.getOrientation();
        int childCount = manager.getChildCount();
        if (orientation == LinearLayout.VERTICAL) {
            drawLinearVertical(childCount, c, parent);
        } else {
            drawLinearHorizontal(childCount, c, parent);
        }
    }

    private void drawLinearHorizontal(int childCount, Canvas c, RecyclerView parent) {
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);
            RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
            int index = i;
            if (hasTitle) {
                if (i == 0) {
                    if (drawOuterBorder) {
                        drawTop(c, child, layoutParams);
                        drawLeft(c, child, layoutParams);
                        drawRight(c, child, layoutParams);
                    }
                    drawBottom(c, child, layoutParams);
                    continue;
                } else {
                    index = i - 1;
                }
            }
            if (needDrawTop(index, NO_SPAN_COUNT, childCount))
                drawTop(c, child, layoutParams);
            if (needDrawBottom(index, NO_SPAN_COUNT, childCount))
                drawBottom(c, child, layoutParams);
            if (needDrawLeft(index, NO_SPAN_COUNT, childCount))
                drawLeft(c, child, layoutParams);
            if (needDrawRight(index, NO_SPAN_COUNT, childCount))
                drawRight(c, child, layoutParams);
        }
    }

    private void drawLinearVertical(int childCount, Canvas c, RecyclerView parent) {
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);
            RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
            int index = i;
            if (hasTitle) {
                if (i == 0) {
                    if (drawOuterBorder) {
                        drawTop(c, child, layoutParams);
                        drawLeft(c, child, layoutParams);
                        drawRight(c, child, layoutParams);
                    }
                    drawBottom(c, child, layoutParams);
                    continue;
                } else {
                    index = i - 1;
                }
            }
            if (needDrawTop(index, ONE_SPAN_COUNT, childCount))
                drawTop(c, child, layoutParams);
            if (needDrawBottom(index, ONE_SPAN_COUNT, childCount))
                drawBottom(c, child, layoutParams);
            if (needDrawLeft(index, ONE_SPAN_COUNT, childCount))
                drawLeft(c, child, layoutParams);
            if (needDrawRight(index, ONE_SPAN_COUNT, childCount))
                drawRight(c, child, layoutParams);
        }
    }

    private void drawGrid(Canvas c, RecyclerView parent) {
        GridLayoutManager manager = (GridLayoutManager) parent.getLayoutManager();
        int spanCount = manager.getSpanCount();
        int childCount = manager.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);
            RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
            int index = i;
            if (hasTitle) {
                if (i == 0) {
                    if (drawOuterBorder) {
                        drawTop(c, child, layoutParams);
                        drawLeft(c, child, layoutParams);
                        drawRight(c, child, layoutParams);
                    }
                    drawBottom(c, child, layoutParams);
                    continue;
                } else {
                    index = i - 1;
                }
            }
            if (needDrawTop(index, spanCount, childCount))
                drawTop(c, child, layoutParams);
            if (needDrawBottom(index, spanCount, childCount))
                drawBottom(c, child, layoutParams);
            if (needDrawLeft(index, spanCount, childCount))
                drawLeft(c, child, layoutParams);
            if (needDrawRight(index, spanCount, childCount))
                drawRight(c, child, layoutParams);
        }
    }

    private boolean needDrawTop(int position, int spanCount, int childCount) {
        if (spanCount == NO_SPAN_COUNT) return drawOuterBorder;
        int currentLine = (position + 1) / spanCount + ((position + 1) % spanCount > 0 ? 1 : 0);
        return drawOuterBorder && currentLine == 1;//需要绘制外边框且第一行
    }

    private void drawTop(Canvas c, View child, RecyclerView.LayoutParams layoutParams) {
        int top = child.getTop() - layoutParams.topMargin - lineWidth;
        int left = child.getLeft() - layoutParams.leftMargin - lineWidth;
        int right = child.getRight() + layoutParams.rightMargin + lineWidth;
        int bottom = top + lineWidth;
        c.drawRect(left, top, right, bottom, mPaint);
    }

    private boolean needDrawLeft(int position, int spanCount, int childCount) {
        if (spanCount == NO_SPAN_COUNT) return drawOuterBorder && position == 0;//水平list首个
        if (drawOuterBorder && spanCount == ONE_SPAN_COUNT) return true;//垂直list
        return drawOuterBorder && (position + 1) % spanCount == 1;//需要绘制外边框且第一列
    }

    private void drawLeft(Canvas c, View child, RecyclerView.LayoutParams layoutParams) {
        int top = child.getTop() - layoutParams.topMargin;
        int left = child.getLeft() - layoutParams.leftMargin - lineWidth;
        int right = left + lineWidth;
        int bottom = child.getBottom() + layoutParams.bottomMargin;
        c.drawRect(left, top, right, bottom, mPaint);
    }

    private boolean needDrawRight(int position, int spanCount, int childCount) {
        if (drawOuterBorder)
            return true;
        if (spanCount == NO_SPAN_COUNT) return true;
        if ((position + 1) % spanCount == 0)
            return false;
        return true;
    }

    private void drawRight(Canvas c, View child, RecyclerView.LayoutParams layoutParams) {
        int top = child.getTop() - layoutParams.topMargin;
        int right = child.getRight() + layoutParams.rightMargin + lineWidth;
        int left = right - lineWidth;
        int bottom = child.getBottom() + layoutParams.bottomMargin;
        c.drawRect(left, top, right, bottom, mPaint);
    }

    private boolean needDrawBottom(int position, int spanCount, int childCount) {
        if (spanCount == NO_SPAN_COUNT) return drawOuterBorder;
        int currentLine = (position + 1) / spanCount + ((position + 1) % spanCount > 0 ? 1 : 0);
        int maxLine = childCount / spanCount + (childCount % spanCount == 0 ? 0 : 1);
        if (currentLine == maxLine && drawOuterBorder)
            return true;
        if (childCount <= spanCount || currentLine == maxLine)//仅一行 或 最后一行
            return false;
        return true;
    }

    private void drawBottom(Canvas c, View child, RecyclerView.LayoutParams layoutParams) {
        int bottom = child.getBottom() + layoutParams.bottomMargin + lineWidth;
        int top = bottom - lineWidth;
        int left = child.getLeft() - layoutParams.leftMargin - lineWidth;
        int right = child.getRight() + layoutParams.rightMargin + lineWidth;
        c.drawRect(left, top, right, bottom, mPaint);
    }

    public MyDividerItemDecoration setLineWidth(int lineWidth) {
        this.lineWidth = lineWidth;
        return this;
    }

    public MyDividerItemDecoration setDrawOuterBorder(boolean drawOuterBorder) {
        this.drawOuterBorder = drawOuterBorder;
        return this;
    }

    public MyDividerItemDecoration setColorString(String colorString) {
        this.colorString = colorString;
        this.mPaint = new Paint();
        this.mPaint.setAntiAlias(true);
        this.mPaint.setStyle(Paint.Style.FILL);
        this.mPaint.setColor(Color.parseColor(colorString));
        return this;
    }

    public MyDividerItemDecoration setColorString5() {
        setColorString("#f2f2f2");
        return this;
    }

    public MyDividerItemDecoration setColorString15() {
        setColorString("#d8d8d8");
        return this;
    }

    public MyDividerItemDecoration setColorString25() {
        setColorString("#bfbfbf");
        return this;
    }

    public MyDividerItemDecoration setColorString35() {
        setColorString("#a5a5a5");
        return this;
    }

    public MyDividerItemDecoration setColorString50() {
        setColorString("#7f7f7f");
        return this;
    }

    public MyDividerItemDecoration setHasTitle(boolean hasTitle) {
        this.hasTitle = hasTitle;
        return this;
    }
}

具体参数

new MyDividerItemDecoration()
      .setColorString("#ff9d1d")//自定义颜色
      .setColorString5()//固定自定义颜色,逐步加深
      .setColorString15()//固定自定义颜色,逐步加深
      .setColorString35()//固定自定义颜色,逐步加深
      .setColorString50()//固定自定义颜色,逐步加深
      .setDrawOuterBorder(true)//设置外边框:默认false
      .setHasTitle(true)//带标题item:默认false
      .setLineWidth(5);//分割线段宽度:默认2

使用demo

RecyclerView recyclerView = findViewById(R.id.recycler_demo1);
recyclerView.setLayoutManager(new LinearLayoutManager(this, RecyclerView.VERTICAL, false));
recyclerView.addItemDecoration(new MyDividerItemDecoration().setDrawOuterBorder(true));
recyclerView.setAdapter(new RecyclerAdapter());


RecyclerView recyclerView2 = findViewById(R.id.recycler_demo2);
recyclerView2.setLayoutManager(new LinearLayoutManager(this, RecyclerView.HORIZONTAL, false));
recyclerView2.addItemDecoration(new MyDividerItemDecoration().setDrawOuterBorder(true));
recyclerView2.setAdapter(new RecyclerAdapter());


RecyclerView recyclerView3 = findViewById(R.id.recycler_demo3);
recyclerView3.setLayoutManager(new GridLayoutManager(this, 3));
recyclerView3.addItemDecoration(new MyDividerItemDecoration().setDrawOuterBorder(false).setColorString("#ff9d1d"));
recyclerView3.setAdapter(new RecyclerAdapter());

获取代码其他方式

GitHub

赠人玫瑰,手有余香

假如文章对你有帮助,那就点个赞吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值