RecyclerView的分割線Decoration,五種實現方式,線性佈局展示

 

上面三張圖片中的item分割線就是效果圖

一、首先定義LinearLayout佈局xml文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/homePageTab02RecyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="5dp">

    </android.support.v7.widget.RecyclerView>

</LinearLayout>

 

二、在activity或fragment中查找View,並設置RecyclerView顯示佈局,一共三種佈局:線性佈局,網格佈局,流式佈局(瀑布佈局)

這裏使用線性佈局方式:recyclerView = view.findViewById(R.id.homePageTab02RecyclerView);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
//通過下面這行設置RecyclerView的佈局顯示方式
recyclerView.setLayoutManager(linearLayoutManager);

三、五種實現分割線的方式

1. 分割線官方提供的方式:最簡單實現
 recyclerView.addItemDecoration(new DividerItemDecoration(getContext(), LinearLayout.VERTICAL));實現效果如下:

2.  使用官方提供的方式,在Drawable自定義一個shape,裏面定義分割線的顏色

  2.1 首先在drawable中創建一個shape:

    

  2.2 代碼中調用如下,就可以實現下圖中這種彩色的分割線:

DividerItemDecoration decoration = new DividerItemDecoration(getContext(),LinearLayout.VERTICAL);
decoration.setDrawable(ContextCompat.getDrawable(getContext(), R.drawable.recycler_item_color));
recyclerView.addItemDecoration(decoration);

 3. 自定義類繼承RecyclerView.ItemDecoration,重寫一些方法來實現

   3.1 下面重寫RecyclerView的ItemDecoration類,建議直接複製如下代碼

public class MyRecyclerViewDecoration extends RecyclerView.ItemDecoration {
    private Context mContext;
    private Drawable mDivider;
    private int mOrientation;
    public static final int HORIZONTAL = LinearLayoutManager.HORIZONTAL;
    public static final int VERTICAL = LinearLayoutManager.VERTICAL;

    //我們通過獲取系統屬性中的listDivider來添加,在系統中的AppTheme中設置
    public static final int[] ATRRS = new int[]{
            android.R.attr.listDivider
    };

    public MyRecyclerViewDecoration(Context context, int orientation) {
        this.mContext = context;
        final TypedArray ta = context.obtainStyledAttributes(ATRRS);
        this.mDivider = ta.getDrawable(0);
        ta.recycle();
        setOrientation(orientation);
    }

    //設置屏幕的方向
    public void setOrientation(int orientation) {
        if (orientation != HORIZONTAL && orientation != VERTICAL) {
            throw new IllegalArgumentException("invalid orientation");
        }
        mOrientation = orientation;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (mOrientation == HORIZONTAL) {
            drawVerticalLine(c, parent, state);
        } else {
            drawHorizontalLine(c, parent, state);
        }
    }

    //畫橫線, 這裏的parent其實是顯示在屏幕顯示的這部分
    public void drawHorizontalLine(Canvas c, RecyclerView parent, RecyclerView.State state) {
        int left = parent.getPaddingLeft();
        int right = parent.getWidth() - parent.getPaddingRight();
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);

            //獲得child的佈局信息
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left + params.leftMargin, top, right - params.leftMargin, bottom);
            mDivider.draw(c);
            //Log.d("wnw", left + " " + top + " "+right+"   "+bottom+" "+i);
        }
    }

    //畫豎線
    public void drawVerticalLine(Canvas c, RecyclerView parent, RecyclerView.State state) {
        int top = parent.getPaddingTop();
        int bottom = parent.getHeight() - parent.getPaddingBottom();
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);

            //獲得child的佈局信息
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicWidth();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    //由於Divider也有長寬高,每一個Item需要向下或者向右偏移
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State
            state) {
        if (mOrientation == HORIZONTAL) {
            //畫橫線,就是往下偏移一個分割線的高度
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else {
            //畫豎線,就是往右偏移一個分割線的寬度
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }
    }
}

3.2 然後在drawable中創建shape,自定義分割線的顏色或樣式

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#22ff00" />
    <size
        android:width="2dp"
        android:height="2dp" />
</shape>

3.3 然後在Style中引用自己的drawable中的自定義顏色選擇器

<item name="android:listDivider">@drawable/recycler_item_color</item>

3.4 調用方式,使用方法:

recyclerView.addItemDecoration(new MyRecyclerViewDecoration(getContext(),MyRecyclerViewDecoration.VERTICAL));或

recyclerView.addItemDecoration(new MyRecyclerViewDecoration(getContext(),LinearLayout.VERTICAL));

3.5 效果圖:

4. 最笨辦法,也相對很簡單的方式實現,在每個item.xml文件中在最下面指定一條分割線

5. 萬能分割線,直接複製即可

public class RecycleViewDivider extends RecyclerView.ItemDecoration {

    private Paint mPaint;
    private Drawable mDivider;
    private int mDividerHeight = 2;//分割線高度,默認爲1px
    private int mOrientation;//列表的方向:LinearLayoutManager.VERTICAL或LinearLayoutManager.HORIZONTAL
    private static final int[] ATTRS = new int[]{android.R.attr.listDivider};

    /**
     * 默認分割線:高度爲2px,顏色爲灰色
     *
     * @param context
     * @param orientation 列表方向
     */
    public RecycleViewDivider(Context context, int orientation) {
        if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {
            throw new IllegalArgumentException("請輸入正確的參數!");
        }
        mOrientation = orientation;

        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
    }

    /**
     * 自定義分割線
     *
     * @param context
     * @param orientation 列表方向
     * @param drawableId  分割線圖片
     */
    public RecycleViewDivider(Context context, int orientation, int drawableId) {
        //this(context, orientation);
        mDivider = ContextCompat.getDrawable(context, drawableId);
        mDividerHeight = mDivider.getIntrinsicHeight();
    }

    /**
     * 自定義分割線
     *
     * @param context
     * @param orientation   列表方向
     * @param dividerHeight 分割線高度
     * @param dividerColor  分割線顏色
     */
    public RecycleViewDivider(Context context, int orientation, int dividerHeight, int dividerColor) {
        //this(context, orientation);
        mDividerHeight = dividerHeight;
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(dividerColor);
        mPaint.setStyle(Paint.Style.FILL);
    }


    //獲取分割線尺寸
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
//        outRect.set(0, 0, 0, mDividerHeight);
        if (mOrientation == LinearLayoutManager.VERTICAL) {
            outRect.set(0, 0, 0, mDividerHeight);
        } else {
            outRect.set(0, 0, mDividerHeight, 0);
        }
    }

    //繪製分割線
    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        if (mOrientation == LinearLayoutManager.VERTICAL) {
            drawVertical(c, parent);
        } else {
            drawHorizontal(c, parent);
        }
    }

    //繪製橫向 item 分割線
    private void drawHorizontal(Canvas canvas, RecyclerView parent) {
        final int left = parent.getPaddingLeft();
        final int right = parent.getMeasuredWidth() - parent.getPaddingRight();
        final int childSize = parent.getChildCount();
        for (int i = 0; i < childSize; i++) {
            final View child = parent.getChildAt(i);
            RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
            final int top = child.getBottom() + layoutParams.bottomMargin;
            final int bottom = top + mDividerHeight;
            if (mDivider != null) {
                mDivider.setBounds(left, top, right, bottom);
                mDivider.draw(canvas);
            }
            if (mPaint != null) {
                canvas.drawRect(left, top, right, bottom, mPaint);
            }
        }
    }

    //繪製縱向 item 分割線
    private void drawVertical(Canvas canvas, RecyclerView parent) {
        final int top = parent.getPaddingTop();
        final int bottom = parent.getMeasuredHeight() - parent.getPaddingBottom();
        final int childSize = parent.getChildCount();
        for (int i = 0; i < childSize; i++) {
            final View child = parent.getChildAt(i);
            RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
            final int left = child.getRight() + layoutParams.rightMargin;
            final int right = left + mDividerHeight;
            if (mDivider != null) {
                mDivider.setBounds(left, top, right, bottom);
                mDivider.draw(canvas);
            }
            if (mPaint != null) {
                canvas.drawRect(left, top, right, bottom, mPaint);
            }
        }
    }
}

使用方法:
recyclerView.addItemDecoration(new RecycleViewDivider(
getActivity(), LinearLayoutManager.VERTICAL, 1, getResources().getColor(R.color.xxx)));

第五種萬能分隔符效果圖: 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章