一款实用的RecyclerView的线性布局分割线

来源:互联网 发布:手机淘宝安全中心登入 编辑:程序博客网 时间:2024/06/05 11:44

       RecyclerView的功能十分强大,但要为其添加分割线却不如ListView那么简单。但是RecyclerView的分割线远比ListView的灵活,那怎样优雅地为RecyclerView添加分割线呢?封装一个继承自ItemDecoration的类即可。以下为我参照多方资料封装的分割线类,希望能为广大同胞们出一份力,让各位单身狗们能够有更多的时间去撩妹。

import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Rect;import android.graphics.drawable.ColorDrawable;import android.graphics.drawable.Drawable;import android.support.annotation.IntDef;import android.support.v4.view.ViewCompat;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.util.SparseArray;import android.util.SparseIntArray;import android.view.View;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;public class LinearDivider extends RecyclerView.ItemDecoration {    public static final int HORIZONTAL = LinearLayoutManager.HORIZONTAL;    public static final int VERTICAL = LinearLayoutManager.VERTICAL;    private static final int[] ATTRS = new int[]{            android.R.attr.listDivider    };    private final SparseIntArray mDividerOffsets = new SparseIntArray();    private final SparseArray<DrawableCreator> mTypeDrawableFactories = new SparseArray<>();    @IntDef({            HORIZONTAL,            VERTICAL    })    @Retention(RetentionPolicy.SOURCE)    private @interface Orientation {    }    @Orientation    private int mOrientation;    private Drawable mDivider;    private boolean isIncludeEdge;    private int mSize;    public LinearDivider(Context context) {        this.isIncludeEdge = false;        resolveDivider(context);        setOrientation(VERTICAL);    }    private void resolveDivider(Context context) {        final TypedArray a = context.obtainStyledAttributes(ATTRS);        mDivider = a.getDrawable(0);        a.recycle();    }    public LinearDivider(int mColor, int mSize) {        this.mDivider = new ColorDrawable(mColor);        this.mSize = mSize;        this.isIncludeEdge = false;        setOrientation(VERTICAL);    }    public LinearDivider(int mColor, int mSize, @Orientation int orientation) {        this.isIncludeEdge = false;        this.mDivider = new ColorDrawable(mColor);        this.mSize = mSize;        setOrientation(orientation);    }    public LinearDivider(int mColor, int mSize, boolean isIncludeEdge) {        this.isIncludeEdge = isIncludeEdge;        this.mDivider = new ColorDrawable(mColor);        this.mSize = mSize;        setOrientation(VERTICAL);    }    public LinearDivider(int mColor, int mSize, @Orientation int orientation, boolean isIncludeEdge) {        this.isIncludeEdge = isIncludeEdge;        this.mDivider = new ColorDrawable(mColor);        this.mSize = mSize;        setOrientation(orientation);    }    public void setOrientation(@Orientation int orientation) {        mOrientation = orientation;    }    public void setDivider(Drawable divider) {        this.mDivider = divider;    }    public void setColor(int mColor) {        this.mDivider = new ColorDrawable(mColor);    }    public void setSize(int mSize) {        this.mSize = mSize;    }    public void setIncludeEdge(boolean isIncludeEdge) {        this.isIncludeEdge = isIncludeEdge;    }    @Override    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {        if (mOrientation == VERTICAL) {            drawVerticalDividers(c, parent);        } else {            drawHorizontalDividers(c, parent);        }    }    private void drawVerticalDividers(Canvas c, RecyclerView parent) {        final int left = parent.getPaddingLeft();        final int right = parent.getWidth() - parent.getPaddingRight();        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 Drawable divider = getDivider(parent, params.getViewAdapterPosition());            final int top = child.getBottom() + params.bottomMargin + Math.round(ViewCompat.getTranslationY(child));            final int bottom = top + mSize;            mDividerOffsets.put(params.getViewAdapterPosition(), mSize);            if (isIncludeEdge && i == 0) {                final int edgeTop = child.getTop() - params.topMargin - mSize;                final int edgeBottom = child.getTop() - params.topMargin;                divider.setBounds(left, edgeTop, right, edgeBottom);                divider.draw(c);            }            if (isIncludeEdge || i != childCount - 1) {                divider.setBounds(left, top, right, bottom);                divider.draw(c);            }        }    }    private void drawHorizontalDividers(Canvas c, RecyclerView parent) {        final int top = parent.getPaddingTop();        final int bottom = parent.getHeight() - parent.getPaddingBottom();        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 Drawable divider = getDivider(parent, params.getViewAdapterPosition());            final int left = child.getRight() + params.rightMargin + Math.round(ViewCompat.getTranslationX(child));            final int right = left + mSize;            mDividerOffsets.put(params.getViewAdapterPosition(), mSize);            if (isIncludeEdge && i == 0) {                final int edgeLeft = child.getLeft() - params.leftMargin - mSize;                final int edgeRight = child.getLeft() - params.leftMargin;                divider.setBounds(edgeLeft, top, edgeRight, bottom);                divider.draw(c);            }            if (isIncludeEdge || i != childCount - 1) {                divider.setBounds(left, top, right, bottom);                divider.draw(c);            }        }    }    @Override    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {        final int adapterPosition = parent.getChildAdapterPosition(view);        int edge = 0;        if (isIncludeEdge) {            if (adapterPosition == 0) {                edge = mSize;            }        } else {            if (adapterPosition == parent.getAdapter().getItemCount() - 1) {                return;            }        }        if (mDividerOffsets.indexOfKey(adapterPosition) < 0) {            mDividerOffsets.put(adapterPosition, mSize);        }        if (mOrientation == VERTICAL) {            outRect.set(0, edge, 0, mDividerOffsets.get(parent.getChildAdapterPosition(view)));        } else {            outRect.set(edge, 0, mDividerOffsets.get(parent.getChildAdapterPosition(view)), 0);        }    }    private Drawable getDivider(RecyclerView parent, int adapterPosition) {        final RecyclerView.Adapter adapter = parent.getAdapter();        final int itemType = adapter.getItemViewType(adapterPosition);        final DrawableCreator drawableCreator = mTypeDrawableFactories.get(itemType);        if (drawableCreator != null) {            return drawableCreator.create(parent, adapterPosition);        }        return mDivider;    }    interface DrawableCreator {        Drawable create(RecyclerView parent, int adapterPosition);    }}
      注意,这个分割线只供使用LinearLayoutManager的RecyclerView使用,方向可以是水平的,也可以是竖直的。里面定义了好几种构造方法,可以直接传一个int型的color和int型的size,就可以创建一个指定颜色和指定宽度的分割线了,也可以通过setDivider传入一个drawable的参数来创建自定义样式的分割线,还可以再传入方向orientation和边界是否有分割线isIncludeEdge的参数直接对分割线进行定制,最后再调recyclerView.addItemDecoration(创建的分割线)就可以了。

      觉得好用还请点个赞哟。

0 0
原创粉丝点击