/* * Created by LuaView. * Copyright (c) 2017, Alibaba Group. All rights reserved. * * This source code is licensed under the MIT. * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. */ package com.taobao.luaview.view.recyclerview.decoration; import android.graphics.Rect; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.view.View; /** * Divider Grid for RecyclerView * @author song */ public class DividerGridItemDecoration extends RecyclerView.ItemDecoration { private int mHalfSpacingWidth; private int mHalfSpacingHeight; public DividerGridItemDecoration(int spacing) { this(spacing, spacing); } public DividerGridItemDecoration(int horizontalSpacing, int verticalSpacing) { this.mHalfSpacingWidth = horizontalSpacing / 2; this.mHalfSpacingHeight = verticalSpacing / 2; } /** * get total Span Count * * @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; } /** * get span index of given view in row * * @param view * @return */ private int getSpanIndex(View view) { if (view.getLayoutParams() instanceof GridLayoutManager.LayoutParams) { return ((GridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex(); } else if (view.getLayoutParams() instanceof RecyclerView.LayoutParams) { return ((StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex(); } return 0; } /** * get span size of given view in row * * @param view * @return */ private int getSpanSize(View view) { if (view.getLayoutParams() instanceof GridLayoutManager.LayoutParams) { return ((GridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanSize(); } else if (view.getLayoutParams() instanceof StaggeredGridLayoutManager.LayoutParams) { return 1; } return 0; } /** * is given view align left of given row * * @param view * @return */ private boolean isLeft(View view, int totalSpanCount) { return getSpanIndex(view) == 0 && getSpanSize(view) < totalSpanCount; } /** * is given view align right of given row * * @param view * @param totalSpanCount * @return */ private boolean isRight(View view, int totalSpanCount) { return getSpanIndex(view) > 0 && (getSpanIndex(view) + getSpanSize(view) == totalSpanCount); } /** * is given view is full span * * @param view * @param totalSpanCount * @return */ private boolean isFull(View view, int totalSpanCount) { return getSpanSize(view) == totalSpanCount; } /** * is position align top of recycler view * 从当前位置找起,只要找到一个跟自己的spanIndex一样的就说明不是第一行,或者已经查找过的spancount >= spanCount说明不是第一行 * * @param parent * @param position * @param totalSpanCount * @return */ private boolean isTop(RecyclerView parent, int position, int totalSpanCount) { if (parent.getLayoutManager() instanceof GridLayoutManager) { GridLayoutManager.SpanSizeLookup sizeLookup = ((GridLayoutManager) parent.getLayoutManager()).getSpanSizeLookup(); if (sizeLookup != null) { int currentSpanIndex = sizeLookup.getSpanIndex(position, totalSpanCount); int lookupedSpanCount = 0; for (int i = position - 1; i >= 0; i--) { lookupedSpanCount = lookupedSpanCount + sizeLookup.getSpanSize(i); if (lookupedSpanCount >= totalSpanCount) { return false; } if (sizeLookup.getSpanIndex(i, totalSpanCount) == currentSpanIndex) { return false; } } return true; } } else if (parent.getLayoutManager() instanceof StaggeredGridLayoutManager) { return position < totalSpanCount;//staggered 的每一列一个span } return false; } /** * is view align bottom of recycler view * 从当前位置向后找,如果找到一个spanIndex = 0的,说明不是最后一行 * * @param parent * @param position * @param totalSpanCount * @return */ private boolean isBottom(RecyclerView parent, int position, int totalSpanCount) { if (parent.getLayoutManager() instanceof GridLayoutManager) { GridLayoutManager.SpanSizeLookup sizeLookup = ((GridLayoutManager) parent.getLayoutManager()).getSpanSizeLookup(); if (sizeLookup != null && parent.getAdapter() != null) { int totalItemCount = parent.getAdapter().getItemCount(); for (int i = position + 1; i < totalItemCount; i--) { if (sizeLookup.getSpanIndex(i, totalSpanCount) == 0) { return false; } } return true; } } else if (parent.getLayoutManager() instanceof StaggeredGridLayoutManager) { int totalItemCount = parent.getAdapter() != null ? parent.getAdapter().getItemCount() : 0; return position + (totalSpanCount - position % totalSpanCount) >= totalItemCount;//如果下一行的第一个不存在则说明是最后一行 } return false; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { final int totalSpanCount = getSpanCount(parent); final int itemPosition = parent.getChildPosition(view); final boolean isLeft = isLeft(view, totalSpanCount); final boolean isRight = isRight(view, totalSpanCount); final boolean isFull = isFull(view, totalSpanCount); final boolean isCenter = !isLeft && !isRight && !isFull; final boolean isTop = isTop(parent, itemPosition, totalSpanCount); final boolean isBottom = isBottom(parent, itemPosition, totalSpanCount); // LogUtil.d(itemPosition, "total:"+totalSpanCount, "index:"+getSpanIndex(view), "Size:"+getSpanSize(view), isLeft, isTop, isRight, isBottom, isFull, isCenter); final int left = (isRight || isCenter) ? mHalfSpacingWidth : 0; final int right = (isLeft || isCenter) ? mHalfSpacingWidth : 0; final int top = !isTop ? mHalfSpacingHeight : 0; final int bottom = !isBottom ? mHalfSpacingHeight : 0; outRect.set(left, top, right, bottom); } }