1. 程式人生 > >RecyclerView的萬能分割線

RecyclerView的萬能分割線

//新增自定義分割線
RecyclerViewDivider divider = new RecyclerViewDivider ();
divider.setMargin(getActivity(), 72, 0 , 0, 0);
recyclerView.addItemDecoration(divider);


import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.LinearLayout;

/**
 * @author fz
 * @date 2018/11/8
 * describe:
 */
public class RecyclerViewDivider extends RecyclerView.ItemDecoration {

    private Drawable mDivider;
    private int mDividerHeight = 1;//px
    private Paint mPaint;
    private Paint mMarginPaint;

    private int mOrientation;

    private final Rect mBounds = new Rect();
    private Rect mMarginBounds;

    private int mMarginColor = 0XFFFFFFFF;
    private int mDividerColor = 0XFFE2E2E2;

    public RecyclerViewDivider() {
        mOrientation = LinearLayout.VERTICAL;
    }

    public RecyclerViewDivider(boolean isVertical) {
        if (isVertical) {
            mOrientation = LinearLayout.VERTICAL;
        } else {
            mOrientation = LinearLayout.HORIZONTAL;
        }
    }

    public void setDividerHeight(int px) {
        this.mDividerHeight = px;
    }

    public void setDividerHeight(Context c, int dp) {
        this.mDividerHeight = (int) (dp * c.getResources().getDisplayMetrics().density);
    }

    public void setDrawable(@NonNull Drawable drawable) {
        mDivider = drawable;
    }

    public void setColor(int color) {
        mPaint = new Paint();
        mPaint.setColor(color);
    }

    public void setColor(Context c, @ColorRes int colorId) {
        setColor(ContextCompat.getColor(c, colorId));
    }

    public void setMarginColor(int color) {
        mMarginPaint = new Paint();
        mMarginPaint.setColor(color);
    }

    public void setMarginColor(Context c, @ColorRes int colorId) {
        setMarginColor(ContextCompat.getColor(c, colorId));
    }

    public void setMargin(int left, int top, int right, int bottom) {
        mMarginBounds = new Rect();
        mMarginBounds.left = left;
        mMarginBounds.top = top;
        mMarginBounds.right = right;
        mMarginBounds.bottom = bottom;
    }

    public void setMargin(Context c, int leftDp, int topDp, int rightDp, int bottomDp) {
        float density = c.getResources().getDisplayMetrics().density;
        mMarginBounds = new Rect();
        mMarginBounds.left = (int) (leftDp * density);
        mMarginBounds.top = (int) (topDp * density);
        mMarginBounds.right = (int) (rightDp * density);
        mMarginBounds.bottom = (int) (bottomDp * density);
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (parent.getLayoutManager() == null) {
            return;
        }
        if (mOrientation == LinearLayout.VERTICAL) {
            drawVertical(c, parent);
        } else {
            drawHorizontal(c, parent);
        }
    }

    /**
     * 繪製縱向列表時的分隔線  這時分隔線是橫著的
     * 每次 left相同,top根據child變化,right相同,bottom也變化
     *
     * @param canvas
     * @param parent
     */
    @SuppressLint("NewApi")
    private void drawVertical(Canvas canvas, RecyclerView parent) {
        canvas.save();
        final int left;
        final int right;
        if (parent.getClipToPadding()) {
            left = parent.getPaddingLeft();
            right = parent.getWidth() - parent.getPaddingRight();
            canvas.clipRect(left, parent.getPaddingTop(), right,
                    parent.getHeight() - parent.getPaddingBottom());
        } else {
            left = 0;
            right = parent.getWidth();
        }

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount - 1; i++) {
            final View child = parent.getChildAt(i);
            parent.getDecoratedBoundsWithMargins(child, mBounds);
            final int bottom = mBounds.bottom + Math.round(ViewCompat.getTranslationY(child));
            int top = bottom - mDividerHeight;
            //根據drawable來繪製分割線
            if (null != mDivider) {
                int sicWidth = mDivider.getIntrinsicWidth();
                if (sicWidth > 0) {
                    top = bottom - sicWidth;
                }
                if (null != mMarginBounds) {
                    mDivider.setBounds(left + mMarginBounds.left, top + mMarginBounds.top,
                            right - mMarginBounds.right, bottom - mMarginBounds.bottom);
                } else {
                    mDivider.setBounds(left, top, right, bottom);
                }
                mDivider.draw(canvas);
                continue;
            }

            if (null == mPaint) {
                mPaint = new Paint();
                mPaint.setColor(mDividerColor);
            }
            //繪製普通分割線
            if (null == mMarginBounds) {
                canvas.drawRect(left, top, right, bottom, mPaint);
                continue;
            }

            //繪製含間距分割線
            if (null == mMarginPaint) {
                mMarginPaint = new Paint();
                mMarginPaint.setColor(mMarginColor);
            }
            if (mMarginBounds.left > 0) {
                canvas.drawRect(0, top + mMarginBounds.top, mMarginBounds.left, bottom - mMarginBounds.bottom, mMarginPaint);
            }
            if (mMarginBounds.right > 0) {
                canvas.drawRect(right - mMarginBounds.right, top + mMarginBounds.top, mMarginBounds.right, bottom - mMarginBounds.bottom, mMarginPaint);
            }
            canvas.drawRect(left + mMarginBounds.left, top + mMarginBounds.top, right - mMarginBounds.right, bottom - mMarginBounds.bottom, mPaint);
        }
        canvas.restore();
    }

    /**
     * 繪製橫向列表時的分隔線  這時分隔線是豎著的
     * l、r 變化; t、b 不變
     *
     * @param canvas
     * @param parent
     */
    private void drawHorizontal(Canvas canvas, RecyclerView parent) {
        canvas.save();
        final int top;
        final int bottom;
        if (parent.getClipToPadding()) {
            top = parent.getPaddingTop();
            bottom = parent.getHeight() - parent.getPaddingBottom();
            canvas.clipRect(parent.getPaddingLeft(), top,
                    parent.getWidth() - parent.getPaddingRight(), bottom);
        } else {
            top = 0;
            bottom = parent.getHeight();
        }

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount - 1; i++) {
            final View child = parent.getChildAt(i);
            parent.getLayoutManager().getDecoratedBoundsWithMargins(child, mBounds);
            int right = mBounds.right + Math.round(ViewCompat.getTranslationX(child));
            int left = right - mDividerHeight;
            //根據drawable來繪製分割線
            if (null != mDivider) {
                int sicWidth = mDivider.getIntrinsicWidth();
                if (sicWidth > 0) {
                    left = right - sicWidth;
                }
                if (null != mMarginBounds) {
                    mDivider.setBounds(left + mMarginBounds.left, top + mMarginBounds.top,
                            right - mMarginBounds.right, bottom - mMarginBounds.bottom);
                } else {
                    mDivider.setBounds(left, top, right, bottom);
                }
                mDivider.draw(canvas);

                continue;
            }

            if (null == mPaint) {
                mPaint = new Paint();
                mPaint.setColor(mDividerColor);
            }
            //繪製普通分割線
            if (null == mMarginBounds){
                canvas.drawRect(left, top, right, bottom, mPaint);
                continue;
            }

            //繪製含間距分割線
            if (null == mMarginPaint) {
                mMarginPaint = new Paint();
                mMarginPaint.setColor(mMarginColor);
            }
            if (mMarginBounds.top > 0){
                canvas.drawRect(left + mMarginBounds.left, 0, right - mMarginBounds.right, mMarginBounds.top, mMarginPaint);
            }
            if (mMarginBounds.bottom > 0){
                canvas.drawRect(left + mMarginBounds.left, bottom - mMarginBounds.bottom, right - mMarginBounds.right, bottom, mPaint);
            }
            canvas.drawRect(left + mMarginBounds.left, top + mMarginBounds.top, right - mMarginBounds.right, bottom - mMarginBounds.bottom, mPaint);
        }
        canvas.restore();
    }

    //獲取分割線尺寸
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        if (mOrientation == LinearLayout.VERTICAL) {
            if (0 == mDividerHeight && null != mDivider) {
                outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());

            } else {
                outRect.set(0, 0, 0, mDividerHeight);
            }
        } else {
            if (0 == mDividerHeight && null != mDivider) {
                outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
            } else {
                outRect.set(0, 0, mDividerHeight, 0);
            }
        }
    }
}