1. 程式人生 > >RecyclerView在GridLayoutManager情況下實現四周都有分割線的ItemDecoration

RecyclerView在GridLayoutManager情況下實現四周都有分割線的ItemDecoration

之前UI有個比較特別的需求,一個gridview形式的列表,但是四周都有白色的分割線:
這裡寫圖片描述

類似這個效果,一開始以為會比較簡單,然後寫了之後才發現,目前網上找到的大部分方法話分割線都是省略掉螢幕邊緣的部分的,
即第一行 第一列 最後一行 最後一列的沒有分割線的

於是在掘金和github找了很久,終於找到一個符合一般要求的—最後一行也與分割線,雖然第一行還是沒有,不過既然最後一行都有了,第一韓有也不難了

這個部落格貼出的ItemDecoration正好拿來改造一番

關鍵程式碼在於:

 private boolean isfirstRow(RecyclerView parent, int
pos, int spanCount, int childCount) { RecyclerView.LayoutManager layoutManager = parent.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { // childCount = childCount - childCount % spanCount; int lines = childCount % spanCount == 0
? childCount / spanCount : childCount / spanCount + 1; //如是第一行則返回true if ((pos / spanCount + 1) == 1) { return true; } else { return false; } } else if (layoutManager instanceof StaggeredGridLayoutManager) { int
orientation = ((StaggeredGridLayoutManager) layoutManager) .getOrientation(); // StaggeredGridLayoutManager 且縱向滾動 if (orientation == StaggeredGridLayoutManager.VERTICAL) { childCount = childCount - childCount % spanCount; // 如果是最後一行,則不需要繪製底部 if (pos >= childCount) return true; } else { // 如果是最後一行,則不需要繪製底部 if ((pos + 1) % spanCount == 0) { return true; } } } return false; }

在這個方法裡判斷當前是否是第一行 (pos / spanCount + 1) == 1 這個就是關鍵程式碼
然後在getItemOffsets()方法中做一個判斷

 if (isfirstRow) {
            top = (spanCount - 1) * mDividerWidth / spanCount;
        } else {
            top = 0;
        }
outRect.set(left, top, right, bottom);

計算item的偏差值,如果是第一行則set上去.

一下為全部程式碼:

package Tools;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.ColorInt;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View;

/**
 * Gridview
 * 四周都是分割線的ItemDecoration,因為網上都是RecyclerView的邊框部分沒有分割線,主要程式碼在於用isfirstRow去判斷
 * Created by _SOLID
 * Date:2016/10/8
 * Time:16:50
 * Desc:
 */


public class GridDividerItemDecoration extends RecyclerView.ItemDecoration {
    private Paint mPaint;
    private int mDividerWidth;

    public GridDividerItemDecoration(int height, @ColorInt int color) {
        mDividerWidth = height;
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(color);
        mPaint.setStyle(Paint.Style.FILL);
    }


    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        int itemPosition = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewLayoutPosition();
        int spanCount = getSpanCount(parent);
        int childCount = parent.getAdapter().getItemCount();

        boolean isLastRow = isLastRow(parent, itemPosition, spanCount, childCount);
        boolean isfirstRow = isfirstRow(parent, itemPosition, spanCount, childCount);

        int top;
        int left;
        int right;
        int bottom;
        int eachWidth = (spanCount - 1) * mDividerWidth / spanCount;
        int dl = mDividerWidth - eachWidth;

        left = itemPosition % spanCount * dl;
        right = eachWidth - left;
        bottom = mDividerWidth;
        //Log.e("zzz", "itemPosition:" + itemPosition + " |left:" + left + " right:" + right + " bottom:" + bottom);
//        if (isLastRow) {
//            bottom = 0;
//        }
        if (isfirstRow) {
            top = (spanCount - 1) * mDividerWidth / spanCount;
        } else {
            top = 0;
        }
        outRect.set(left, top, right, bottom);

    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        draw(c, parent);
    }

    //繪製橫向 item 分割線
    private void draw(Canvas canvas, RecyclerView parent) {
        int childSize = parent.getChildCount();
        for (int i = 0; i < childSize; i++) {
            View child = parent.getChildAt(i);
            RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();

            //畫水平分隔線
            int left = child.getLeft();
            int right = child.getRight();
            int top = child.getBottom() + layoutParams.bottomMargin;
            int bottom = top + mDividerWidth;
            if (mPaint != null) {
                canvas.drawRect(left, top, right, bottom, mPaint);
            }
            //畫垂直分割線
            top = child.getTop();
            bottom = child.getBottom() + mDividerWidth;
            left = child.getRight() + layoutParams.rightMargin;
            right = left + mDividerWidth;
            if (mPaint != null) {
                canvas.drawRect(left, top, right, bottom, mPaint);
            }
        }
    }

    private boolean isLastColumn(RecyclerView parent, int pos, int spanCount,
                                 int childCount) {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            if ((pos + 1) % spanCount == 0) {// 如果是最後一列,則不需要繪製右邊
                return true;
            }
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            if (orientation == StaggeredGridLayoutManager.VERTICAL) {
                if ((pos + 1) % spanCount == 0)// 如果是最後一列,則不需要繪製右邊
                {
                    return true;
                }
            } else {
                childCount = childCount - childCount % spanCount;
                if (pos >= childCount)// 如果是最後一列,則不需要繪製右邊
                    return true;
            }
        }
        return false;
    }

    private boolean isLastRow(RecyclerView parent, int pos, int spanCount,
                              int childCount) {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            // childCount = childCount - childCount % spanCount;
            int lines = childCount % spanCount == 0 ? childCount / spanCount : childCount / spanCount + 1;
            return lines == pos / spanCount + 1;
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            // StaggeredGridLayoutManager 且縱向滾動
            if (orientation == StaggeredGridLayoutManager.VERTICAL) {
                childCount = childCount - childCount % spanCount;
                // 如果是最後一行,則不需要繪製底部
                if (pos >= childCount)
                    return true;
            } else {
                // 如果是最後一行,則不需要繪製底部
                if ((pos + 1) % spanCount == 0) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean isfirstRow(RecyclerView parent, int pos, int spanCount,
                               int childCount) {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            // childCount = childCount - childCount % spanCount;
            int lines = childCount % spanCount == 0 ? childCount / spanCount : childCount / spanCount + 1;
            //如是第一行則返回true
            if ((pos / spanCount + 1) == 1) {
                return true;
            } else {
                return false;
            }
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            // StaggeredGridLayoutManager 且縱向滾動
            if (orientation == StaggeredGridLayoutManager.VERTICAL) {
                childCount = childCount - childCount % spanCount;
                // 如果是最後一行,則不需要繪製底部
                if (pos >= childCount)
                    return true;
            } else {
                // 如果是最後一行,則不需要繪製底部
                if ((pos + 1) % spanCount == 0) {
                    return true;
                }
            }
        }
        return false;
    }

    private int getSpanCount(RecyclerView parent) {
        // 列數
        int spanCount = -1;
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {

            spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            spanCount = ((StaggeredGridLayoutManager) layoutManager)
                    .getSpanCount();
        }
        return spanCount;
    }
}