package com.doumee.lib_coremodel.binding.viewadapter.recyclerview; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.view.View; import androidx.recyclerview.widget.RecyclerView; /** * Created by goldze on 2017/6/16. */ public class DividerLine extends RecyclerView.ItemDecoration { private static final String TAG = DividerLine.class.getCanonicalName(); //默认分隔线厚度为2dp private static final int DEFAULT_DIVIDER_SIZE = 1; //控制分隔线的属性,值为一个drawable private static final int ATTRS[] = {android.R.attr.listDivider}; //divider对应的drawable private Drawable dividerDrawable; private Context mContext; private int dividerSize; //默认为null private LineDrawMode mMode = null; /** * 分隔线绘制模式,水平,垂直,两者都绘制 */ public enum LineDrawMode { HORIZONTAL, VERTICAL, BOTH } public DividerLine(Context context) { mContext = context; //获取样式中对应的属性值 TypedArray attrArray = context.obtainStyledAttributes(ATTRS); dividerDrawable = attrArray.getDrawable(0); attrArray.recycle(); } public DividerLine(Context context, LineDrawMode mode) { this(context); mMode = mode; } public DividerLine(Context context, int dividerSize, LineDrawMode mode) { this(context, mode); this.dividerSize = dividerSize; } public int getDividerSize() { return dividerSize; } public void setDividerSize(int dividerSize) { this.dividerSize = dividerSize; } public LineDrawMode getMode() { return mMode; } public void setMode(LineDrawMode mode) { mMode = mode; } /** * Item绘制完毕之后绘制分隔线 * 根据不同的模式绘制不同的分隔线 * * @param c * @param parent * @param state */ @Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDrawOver(c, parent, state); if (getMode() == null) { throw new IllegalStateException("assign LineDrawMode,please!"); } switch (getMode()) { case VERTICAL: drawVertical(c, parent, state); break; case HORIZONTAL: drawHorizontal(c, parent, state); break; case BOTH: drawHorizontal(c, parent, state); drawVertical(c, parent, state); break; } } /** * 绘制垂直分隔线 * * @param c * @param parent * @param state */ private void drawVertical(Canvas c, RecyclerView parent, RecyclerView.State state) { final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); final int top = child.getTop() - params.topMargin; final int bottom = child.getBottom() + params.bottomMargin; final int left = child.getRight() + params.rightMargin; final int right = getDividerSize() == 0 ? left + dip2px(mContext, DEFAULT_DIVIDER_SIZE) : left + getDividerSize(); dividerDrawable.setBounds(left, top, right, bottom); dividerDrawable.draw(c); } } /** * 绘制水平分隔线 * * @param c * @param parent * @param state */ private void drawHorizontal(Canvas c, RecyclerView parent, RecyclerView.State state) { int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { //分别为每个item绘制分隔线,首先要计算出item的边缘在哪里,给分隔线定位,定界 final View child = parent.getChildAt(i); //RecyclerView的LayoutManager继承自ViewGroup,支持了margin final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); //child的左边缘(也是分隔线的左边) final int left = child.getLeft() - params.leftMargin; //child的底边缘(恰好是分隔线的顶边) final int top = child.getBottom() + params.topMargin; //child的右边(也是分隔线的右边) final int right = child.getRight() - params.rightMargin; //分隔线的底边所在的位置(那就是分隔线的顶边加上分隔线的高度) final int bottom = getDividerSize() == 0 ? top + dip2px(mContext, DEFAULT_DIVIDER_SIZE) : top + getDividerSize(); dividerDrawable.setBounds(left, top, right, bottom); //画上去 dividerDrawable.draw(c); } } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); // outRect.bottom = getDividerSize() == 0 ? dip2px(mContext, DEFAULT_DIVIDER_SIZE) : getDividerSize(); } /** * 将dip或dp值转换为px值,保证尺寸大小不变 * * @param dipValue * @param context(DisplayMetrics类中属性density) * @return */ public static int dip2px(Context context, float dipValue) { float scale = context.getResources().getDisplayMetrics().density; return (int) (dipValue * scale + 0.5f); } }