当前位置: 代码迷 >> 综合 >> 一款实用的RecyclerView的线性布局分割线
  详细解决方案

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

热度:90   发布时间:2023-10-25 14:16:00.0

       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 {}@Orientationprivate 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;}@Overridepublic 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);}}}@Overridepublic 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(创建的分割线)就可以了。

      觉得好用还请点个赞哟。