通用的GridDividerItemDecoration

通用的GridDividerItemDecoration特點

1.支持設置左右間距
2.支持設置first item/last item ,top和bottom margin
3.剩餘空間每個item平均分配

package com.starlight.mobile.android.smsone.common;

import android.content.Context;
import android.graphics.Color;
import android.support.v7.widget.StaggeredGridLayoutManager;
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.view.View;

/**
 * Created by Haozi on 2018/10/10 0023.
 */

public class GridDividerItemDecoration extends RecyclerView.ItemDecoration {
    private Paint mPaint;
    private int mDividerWidth;          //您所需指定的間隔寬度,主要爲第一列和最後一列與父控件的間隔;行間距,列間距將動態分配
    private int mFirstRowTopMargin = 0; //第一行頂部是否需要間隔
    private boolean isNeedSpace = false;//第一列和最後一列是否需要指定間隔(默認不指定)
    private boolean isLastRowNeedSpace = false;//最後一行是否需要間隔(默認不需要)
    int spanCount = 0;
    private Context mContext;

    /**
     *
     * @param dividerWidth 間隔寬度
     * @param isNeedSpace 第一列和最後一列是否需要間隔
     */
    public GridDividerItemDecoration(Context context, int dividerWidth, boolean isNeedSpace) {
        this(context,dividerWidth,0,isNeedSpace,false);
    }

    /**
     *
     * @param dividerWidth 間隔寬度
     * @param isNeedSpace 第一列和最後一列是否需要間隔
     * @param firstRowTopMargin 第一行頂部是否需要間隔(根據間隔大小判斷)
     */
    public GridDividerItemDecoration(Context context, int dividerWidth, int firstRowTopMargin, boolean isNeedSpace) {
        this(context,dividerWidth,firstRowTopMargin,isNeedSpace,false);
    }

    /**
     *  @param dividerWidth 間隔寬度
     * @param firstRowTopMargin 第一行頂部是否需要間隔
     * @param isNeedSpace 第一列和最後一列是否需要間隔
     * @param isLastRowNeedSpace 最後一行是否需要間隔
     */
    public GridDividerItemDecoration(Context context, int dividerWidth, int firstRowTopMargin, boolean isNeedSpace, boolean isLastRowNeedSpace) {
        this(context,dividerWidth,firstRowTopMargin,isNeedSpace,isLastRowNeedSpace, Color.WHITE);
    }

    /**
     *  @param dividerWidth 間隔寬度
     * @param firstRowTopMargin 第一行頂部是否需要間隔
     * @param isNeedSpace 第一列和最後一列是否需要間隔
     * @param isLastRowNeedSpace 最後一行是否需要間隔
     */
    public GridDividerItemDecoration(Context context, int dividerWidth, int firstRowTopMargin, boolean isNeedSpace, boolean isLastRowNeedSpace, @ColorInt int color) {
        mDividerWidth = dividerWidth;
        this.isNeedSpace = isNeedSpace;
        this.mContext = context;
        this.isLastRowNeedSpace = isLastRowNeedSpace;
        this.mFirstRowTopMargin = firstRowTopMargin;

        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 top = 0;
        int left = 0;
        int right = 0;
        int bottom = 0;

        int itemPosition = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewLayoutPosition();
        spanCount = getSpanCount(parent);
        int childCount = parent.getAdapter().getItemCount();
        int maxAllDividerWidth = getMaxDividerWidth(view); //

        int spaceWidth = 0;//首尾兩列與父佈局之間的間隔
        if(isNeedSpace)
            spaceWidth = mDividerWidth;

        int eachItemWidth = maxAllDividerWidth/spanCount;//每個Item left+right
        int dividerItemWidth = (maxAllDividerWidth-2*spaceWidth)/(spanCount-1);//item與item之間的距離

        left = itemPosition % spanCount * (dividerItemWidth - eachItemWidth) + spaceWidth;
        right = eachItemWidth - left;
        bottom = mDividerWidth;
        if(mFirstRowTopMargin > 0 && isFirstRow(parent, itemPosition, spanCount, childCount))//第一行頂部是否需要間隔
            top = mFirstRowTopMargin;
        if (!isLastRowNeedSpace && isLastRow(parent, itemPosition, spanCount, childCount)){//最後一行是否需要間隔
            bottom = 0;
        }

        outRect.set(left, top, right, bottom);
    }

    /**
     * 獲取Item View的大小,若無則自動分配空間
     * 並根據 屏幕寬度-View的寬度*spanCount 得到屏幕剩餘空間
     * @param view
     * @return
     */
    private int getMaxDividerWidth(View view) {
        int itemWidth = view.getLayoutParams().width;
        int itemHeight = view.getLayoutParams().height;

        int screenWidth = mContext.getResources().getDisplayMetrics().widthPixels > mContext.getResources().getDisplayMetrics().heightPixels
                ? mContext.getResources().getDisplayMetrics().heightPixels : mContext.getResources().getDisplayMetrics().widthPixels;

        int maxDividerWidth = screenWidth-itemWidth * spanCount;
        if(itemHeight < 0 || itemWidth < 0 || (isNeedSpace && maxDividerWidth <= (spanCount-1) * mDividerWidth)){
            view.getLayoutParams().width = getAttachCloumnWidth();
            view.getLayoutParams().height = getAttachCloumnWidth();

            maxDividerWidth = screenWidth-view.getLayoutParams().width * spanCount;
        }
        return maxDividerWidth;
    }

    /**
     * 根據屏幕寬度和item數量分配 item View的width和height
     * @return
     */
    private int getAttachCloumnWidth() {
        int itemWidth = 0;
        int spaceWidth = 0;
        try {
            int width = mContext.getResources().getDisplayMetrics().widthPixels > mContext.getResources().getDisplayMetrics().heightPixels
                    ? mContext.getResources().getDisplayMetrics().heightPixels : mContext.getResources().getDisplayMetrics().widthPixels;
            if(isNeedSpace)
                spaceWidth = 2 * mDividerWidth;
            itemWidth = (width-spaceWidth) / spanCount - 40;//why - 40???
        } catch (Exception e) {
            e.printStackTrace();
        }

        return itemWidth;
    }

    @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 childCount = parent.getChildCount();
        for (int i = 0; i < childCount; 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);
            }
        }
    }

    /**
     * 判讀是否是第一列
     * @param parent
     * @param pos
     * @param spanCount
     * @param childCount
     * @return
     */
    private boolean isFirstColumn(RecyclerView parent, int pos, int spanCount, int childCount) {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            if (pos % spanCount == 0) {
                return true;
            }
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            if (orientation == StaggeredGridLayoutManager.VERTICAL) {
                if (pos % spanCount == 0) {// 第一列
                    return true;
                }
            } else {

            }
        }
        return false;
    }

    /**
     * 判斷是否是最後一列
     * @param parent
     * @param pos
     * @param spanCount
     * @param childCount
     * @return
     */
    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 {

            }
        }
        return false;
    }

    /**
     * 判讀是否是最後一行
     * @param parent
     * @param pos
     * @param spanCount
     * @param childCount
     * @return
     */
    private boolean isLastRow(RecyclerView parent, int pos, int spanCount, int childCount) {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            int lines = childCount % spanCount == 0 ? childCount / spanCount : childCount / spanCount + 1;
            return lines == pos / spanCount + 1;
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {

        }
        return false;
    }

    /**
     * 判斷是否是第一行
     * @param parent
     * @param pos
     * @param spanCount
     * @param childCount
     * @return
     */
    private boolean isFirstRow(RecyclerView parent, int pos, int spanCount, int childCount) {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            if ((pos / spanCount + 1) == 1) {
                return true;
            } else {
                return false;
            }
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {

        }
        return false;
    }

    /**
     * 獲取列數
     * @param parent
     * @return
     */
    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;
    }
}

github

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