Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

This library is not good for GridLayoutManager. Some Suggesttion. #54

Open
liaolintao opened this issue Jun 10, 2017 · 0 comments
Open

Comments

@liaolintao
Copy link

Problem

Method(com.yqritc.recyclerviewflexibledivider.FlexibleDividerDecoration#getGroupIndex )
calls frequently, and that method consume too much time, ui thread do too much.

google source code :

GridLayoutManager.SpanSizeLookup#getSpanGroupIndex(int, int) .
https://developer.android.com/reference/android/support/v7/widget/GridLayoutManager.SpanSizeLookup.html?hl=ja#getSpanGroupIndex(int;

        public int getSpanGroupIndex(int adapterPosition, int spanCount) {
            int span = 0;
            int group = 0;
            int positionSpanSize = getSpanSize(adapterPosition);
            for (int i = 0; i < adapterPosition; i++) {
                int size = getSpanSize(i);
                span += size;
                if (span == spanCount) {
                    span = 0;
                    group++;
                } else if (span > spanCount) {
                    // did not fit, moving to next row / column
                    span = size;
                    group++;
                }
            }
            if (span + positionSpanSize > spanCount) {
                group++;
            }
            return group;
        }

My Suggesttion

Please dont't frequently use method GridLayoutManager.SpanSizeLookup#getSpanGroupIndex(int, int) .
I do it ,and ui thread is good for show.

My Simple Code for GridLayoutManager

import android.graphics.Canvas;
import android.graphics.Rect;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ItemDecoration;
import android.support.v7.widget.RecyclerView.State;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View;

public class ListSpacingDecoration extends ItemDecoration {

  private static final String TAG = ListSpacingDecoration.class.getSimpleName();

  private static final int VERTICAL = OrientationHelper.VERTICAL;

  private int orientation = -1;
  private int spanCount = -1;
  private int spacing;
  private int halfSpacing;

  public ListSpacingDecoration(int spacing) {
    super();
    this.spacing = spacing;
    this.halfSpacing = spacing / 2;
  }

  /**
   * 可以通过outRect.set()为每个Item设置一定的偏移量,主要用于绘制Decorator
   */
  @Override
  public void getItemOffsets(Rect outRect, final View view, RecyclerView parent, State state) {

    // super.getItemOffsets(outRect, view, parent, state);
    if (orientation == -1) {
      orientation = getOrientation(parent);
    }

    if (spanCount == -1) {
      spanCount = getTotalSpan(parent);
    }

    int childCount = parent.getLayoutManager().getItemCount();
    int childIndex = parent.getChildAdapterPosition(view);

    int itemSpanSize = getItemSpanSize(parent, childIndex);
    int spanIndex = getItemSpanIndex(parent, childIndex);

//    LogUtils.d(TAG, "getItemOffsets childCount = " + childCount + " - childIndex = " + childIndex + " : itemSpanSize = "
//        + itemSpanSize + " : spanIndex = " + spanIndex);
    /* INVALID SPAN */
    if (spanCount < 1)
      return;

    setSpacings(outRect, parent, childCount, childIndex, itemSpanSize, spanIndex);
  }

  /**
   * onDraw方法先于drawChildren
   */
  @Override
  public void onDraw(Canvas c, RecyclerView parent, State state) {
    // TODO
    super.onDraw(c, parent, state);
  }

  /**
   * onDrawOver在drawChildren之后,一般我们选择复写其中一个即可
   */
  @Override
  public void onDrawOver(Canvas c, RecyclerView parent, State state) {
    // TODO
    super.onDrawOver(c, parent, state);
  }

  protected void setSpacings(Rect outRect, RecyclerView parent, int childCount, int childIndex, int itemSpanSize,
      int spanIndex) {

    outRect.top = halfSpacing;
    outRect.bottom = halfSpacing;
    outRect.left = halfSpacing;
    outRect.right = halfSpacing;

    if (isTopEdge(parent, childCount, childIndex, itemSpanSize, spanIndex)) {
      outRect.top = spacing;
    }

    if (isLeftEdge(parent, childCount, childIndex, itemSpanSize, spanIndex)) {
      // outRect.left = spacing;
      outRect.left = 0;
    }

    if (isRightEdge(parent, childCount, childIndex, itemSpanSize, spanIndex)) {
      // outRect.right = spacing;
      outRect.right = 0;
    }

    if (isBottomEdge(parent, childCount, childIndex, itemSpanSize, spanIndex)) {
      outRect.bottom = spacing;
    }
  }

  @SuppressWarnings("all")
  protected int getTotalSpan(RecyclerView parent) {

    RecyclerView.LayoutManager mgr = parent.getLayoutManager();
    if (mgr instanceof GridLayoutManager) {
      return ((GridLayoutManager) mgr).getSpanCount();
    } else if (mgr instanceof StaggeredGridLayoutManager) {
      return ((StaggeredGridLayoutManager) mgr).getSpanCount();
    } else if (mgr instanceof LinearLayoutManager) {
      return 1;
    }

    return -1;
  }

  @SuppressWarnings("all")
  protected int getItemSpanSize(RecyclerView parent, int childIndex) {

    RecyclerView.LayoutManager mgr = parent.getLayoutManager();
    if (mgr instanceof GridLayoutManager) {
      return ((GridLayoutManager) mgr).getSpanSizeLookup().getSpanSize(childIndex);
    } else if (mgr instanceof StaggeredGridLayoutManager) {
      return 1;
    } else if (mgr instanceof LinearLayoutManager) {
      return 1;
    }

    return -1;
  }

  @SuppressWarnings("all")
  protected int getItemSpanIndex(RecyclerView parent, int childIndex) {

    RecyclerView.LayoutManager mgr = parent.getLayoutManager();
    if (mgr instanceof GridLayoutManager) {
      return ((GridLayoutManager) mgr).getSpanSizeLookup().getSpanIndex(childIndex, spanCount);
    } else if (mgr instanceof StaggeredGridLayoutManager) {
      return childIndex % spanCount;
    } else if (mgr instanceof LinearLayoutManager) {
      return 0;
    }

    return -1;
  }

  @SuppressWarnings("all")
  protected int getOrientation(RecyclerView parent) {

    RecyclerView.LayoutManager mgr = parent.getLayoutManager();
    if (mgr instanceof LinearLayoutManager) {
      return ((LinearLayoutManager) mgr).getOrientation();
    } else if (mgr instanceof GridLayoutManager) {
      return ((GridLayoutManager) mgr).getOrientation();
    } else if (mgr instanceof StaggeredGridLayoutManager) {
      return ((StaggeredGridLayoutManager) mgr).getOrientation();
    }

    return VERTICAL;
  }

  protected boolean isLeftEdge(RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) {

    if (orientation == VERTICAL) {

      return spanIndex == 0;

    } else {

      return (childIndex == 0) || isFirstItemEdgeValid((childIndex < spanCount), parent, childIndex);
    }
  }

  protected boolean isRightEdge(RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) {

    if (orientation == VERTICAL) {

      return (spanIndex + itemSpanSize) == spanCount;

    } else {

      return isLastItemEdgeValid((childIndex >= childCount - spanCount), parent, childCount, childIndex, spanIndex);
    }
  }

  protected boolean isTopEdge(RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) {

    if (orientation == VERTICAL) {

      return (childIndex == 0) || isFirstItemEdgeValid((childIndex < spanCount), parent, childIndex);

    } else {

      return spanIndex == 0;
    }
  }

  protected boolean isBottomEdge(RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) {

    if (orientation == VERTICAL) {

      return isLastItemEdgeValid((childIndex >= childCount - spanCount), parent, childCount, childIndex, spanIndex);

    } else {

      return (spanIndex + itemSpanSize) == spanCount;
    }
  }

  protected boolean isFirstItemEdgeValid(boolean isOneOfFirstItems, RecyclerView parent, int childIndex) {

    int totalSpanArea = 0;
    if (isOneOfFirstItems) {
      for (int i = childIndex; i >= 0; i--) {
        totalSpanArea = totalSpanArea + getItemSpanSize(parent, i);
      }
    }

    return isOneOfFirstItems && totalSpanArea <= spanCount;
  }

  protected boolean isLastItemEdgeValid(boolean isOneOfLastItems, RecyclerView parent, int childCount, int childIndex,
      int spanIndex) {

    int totalSpanRemaining = 0;
    if (isOneOfLastItems) {
      for (int i = childIndex; i < childCount; i++) {
        totalSpanRemaining = totalSpanRemaining + getItemSpanSize(parent, i);
      }
    }

    return isOneOfLastItems && (totalSpanRemaining <= spanCount - spanIndex);
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant