RecyclerView 自己动手绘制ItemDecoration分割线

因为RecyclerView越来越普及,使用场景也越来越多,所以在如此高频使用的情况下,分割线也是必不可少的,但是我们经常在不同的场景下使用,对分割线的需求也不一致,导致自己手动编写的分割线并不能满足日常需求,所以我比较常用的做法是在Item布局中编写分割线,久而久之还是觉得用着不方便,索性就写一个扩展性好一点的分割线吧。

使用示例:

//线粗细1dp,线两边边距10dp,线颜色红色
rl.addItemDecoration(new DividerItemDecoration(this, 1f, 10, Color.RED));

预览截图:

未添加分割线

LinearLayoutManager.VERTICAL布局方式

LinearLayoutManager.HORIZONTAL布局方式

GridLayoutManager布局方式

实现代码:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;

/**
 * Created by Chao  2018/6/7 on 14:43
 * description
 */

public class DividerItemDecoration extends RecyclerView.ItemDecoration {
    private int orientation = -1;
    private Drawable divider;
    private int padding;
    private float size = 0;
    private int color = -1;
    private Rect rectF = new Rect();
    private Context context;

    public DividerItemDecoration(Context context) {
        this.context = context;
        initData();
    }

    public DividerItemDecoration(Context context, float size) {
        this.context = context;
        this.size = dip2px(size);
        initData();
    }

    public DividerItemDecoration(Context context, float size, int padding) {
        this.context = context;
        this.size = dip2px(size);
        this.padding = dip2px(padding);
        initData();
    }

    public DividerItemDecoration(Context context, float size, int padding, int color) {
        this.context = context;
        this.size = dip2px(size);
        this.padding = dip2px(padding);
        this.color = color;
        initData();
    }

    private void initData() {
        if (size == 0) {
            size = dip2px(1);
        }
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        //super.onDraw(c, parent, state);
        init(parent);
        c.save();
        if (orientation == LinearLayoutManager.VERTICAL) {
            int left = parent.getPaddingLeft() + padding;
            int right = parent.getWidth() - parent.getPaddingRight() - padding;
            for (int i = 0; i < parent.getChildCount(); i++) {
                View childAt = parent.getChildAt(i);
                RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) childAt.getLayoutParams();
                int top = (int) (childAt.getBottom() + layoutParams.bottomMargin + ViewCompat.getTranslationY(childAt));
                int bottom = top + divider.getIntrinsicHeight();
                divider.setBounds(left, top, right, bottom);
                divider.draw(c);
            }
        } else if (orientation == LinearLayoutManager.HORIZONTAL) {
            int top = parent.getPaddingTop() + padding;
            int bottom = parent.getHeight() - parent.getPaddingBottom() - padding;
            for (int i = 0; i < parent.getChildCount(); i++) {
                View childAt = parent.getChildAt(i);
                parent.getLayoutManager().getDecoratedBoundsWithMargins(childAt, rectF);
//                RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) childAt.getLayoutParams();//使用Google默认分割线的代码,下面获取左右导致无法显示,但上下不使用默认分割线的代码,因为默认的会高度充满
//                int left = (int) (childAt.getLeft() + layoutParams.leftMargin + ViewCompat.getTranslationX(childAt));
//                int right = left + divider.getIntrinsicWidth();
                final int right = rectF.right + Math.round(childAt.getTranslationX());
                final int left = right - divider.getIntrinsicWidth();
                divider.setBounds(left, top, right, childAt.getHeight() - padding);
                divider.draw(c);
            }
        } else if (orientation == 3) {
            for (int i = 0; i < parent.getChildCount(); i++) {
                View childAt = parent.getChildAt(i);
                RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) childAt.getLayoutParams();
                RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
                int spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
                boolean endView = (i + 1) % spanCount == 0;
                if (!endView) {//竖线
                    int left = childAt.getRight() + layoutParams.rightMargin;
                    int right = left + divider.getIntrinsicWidth();
                    int top = childAt.getTop() + layoutParams.topMargin + padding;
                    int bottom = childAt.getBottom() - layoutParams.bottomMargin + divider.getIntrinsicHeight() - padding;
                    divider.setBounds(left, top, right, bottom);
                    divider.draw(c);
                }
                int left = childAt.getLeft() + layoutParams.leftMargin + padding;
                int right = childAt.getRight() - layoutParams.rightMargin + divider.getIntrinsicWidth() - padding;
                int top = childAt.getBottom() + layoutParams.bottomMargin;
                int bottom = top + divider.getIntrinsicHeight();
                divider.setBounds(left, top, right, bottom);
                divider.draw(c);
            }
        }
        c.restore();
    }


    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        init(parent);
        if (orientation == LinearLayoutManager.VERTICAL) {
            outRect.set(0, 0, 0, divider.getIntrinsicHeight());
        } else if (orientation == LinearLayoutManager.HORIZONTAL) {
            outRect.set(0, 0, divider.getIntrinsicWidth(), 0);
        } else if (orientation == 3) {
            outRect.set(0, 0, divider.getIntrinsicWidth(), divider.getIntrinsicHeight());
        }
        //super.getItemOffsets(outRect, view, parent, state);
    }

    private void init(RecyclerView parent) {
        if (orientation == -1) {
            divider = new GradientDrawable();
            ((GradientDrawable) divider).setSize((int) size, (int) size);
            if (color != -1) {
                ((GradientDrawable) divider).setColor(color);
            }
            //divider = ContextCompat.getDrawable(parent.getContext(), R.drawable.item_divider);
            ((GradientDrawable) divider).setCornerRadius(dip2px(5));
            RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
            if (layoutManager instanceof GridLayoutManager) {
                orientation = 3;
            } else if (layoutManager instanceof LinearLayoutManager) {
                LinearLayoutManager manager = (LinearLayoutManager) layoutManager;
                if (manager.getOrientation() == LinearLayoutManager.VERTICAL) {
                    orientation = LinearLayoutManager.VERTICAL;
                } else if (manager.getOrientation() == LinearLayoutManager.HORIZONTAL) {
                    orientation = LinearLayoutManager.HORIZONTAL;
                }
            }
        }
    }

    public int dip2px(float dpValue) {
        final float scale = context.getResources()
                .getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
}

猜你喜欢

转载自blog.csdn.net/c__chao/article/details/80613330