1

I have the same question as is in this post:
RecyclerView GridLayoutManager: how to auto-detect span count?

but for the Staggered GridLayoutManager. I tried to edit the code from this very good answer:

public class StaggeredGridAutofitLayoutManager extends StaggeredGridLayoutManager {
    private int mColumnWidth;
    private boolean mColumnWidthChanged = true;

    public StaggeredGridAutofitLayoutManager(Context context, int columnWidth, int orientation) {
        /* Initially set spanCount to 1, will be changed automatically later. */
        super(1, orientation);
        setColumnWidth(checkedColumnWidth(context, columnWidth));
    }

    private int checkedColumnWidth(Context context, int columnWidth) {
        if (columnWidth <= 0) {
            /* Set default columnWidth value (48dp here). It is better to move this constant
            to static constant on top, but we need context to convert it to dp, so can't really
            do so. */
            columnWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48,
                    context.getResources().getDisplayMetrics());
        }
        return columnWidth;
    }

    public void setColumnWidth(int newColumnWidth) {
        if (newColumnWidth > 0 && newColumnWidth != mColumnWidth) {
            mColumnWidth = newColumnWidth;
            mColumnWidthChanged = true;
        }
    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        if (mColumnWidthChanged && mColumnWidth > 0) {
            int totalSpace;
            if (getOrientation() == VERTICAL) {
                totalSpace = getWidth() - getPaddingRight() - getPaddingLeft();
            } else {
                totalSpace = getHeight() - getPaddingTop() - getPaddingBottom();
            }
            int spanCount = Math.max(1, totalSpace / mColumnWidth);
            setSpanCount(spanCount);
            mColumnWidthChanged = false;
        }
        super.onLayoutChildren(recycler, state);
    }
}

but the application crash with this error:

Cannot call this method while RecyclerView is computing a layout or scrolling
(linked to line => setSpanCount(spanCount));

Can someone please help me with this modification?

Community
  • 1
  • 1
Tomas
  • 4,652
  • 6
  • 31
  • 37

1 Answers1

0

Reason

I had the same problem as you.

The cause of that is framework block method setSpanCount(int spanCount) for StaggeredGridLayoutManager during 'computing a layout or scrolling'.

This is an explanation (found in RecyclerView.java):

/**
 * This variable is incremented during a dispatchLayout and/or scroll.
 * Some methods should not be called during these periods (e.g. adapter data change).
 * Doing so will create hard to find bugs so we better check it and throw an exception.
 *
 * @see #assertInLayoutOrScroll(String)
 * @see #assertNotInLayoutOrScroll(String)
 */
private int mLayoutOrScrollCounter = 0;

So, they checked it and throw you an exception :D


Solution

When I accepted I can't do it in the best way and still don't want to use a ViewTreeObserver solution I changed setSpanCount(spanCount) to:

new Handler(context.getMainLooper()).post(new Runnable() {
       @Override
       public void run() {
            setSpanCount(spanCount);
       }
});
paulina_glab
  • 2,467
  • 2
  • 16
  • 25