13

I have a RecyclerView which I use to show 2 column layout with some items as sections, using the full width. This is how I am setting up my RecyclerView:

StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);
recyclerView.setItemAnimator(null);
recyclerView.setLayoutManager(layoutManager);
recyclerView.addItemDecoration(new SpacesItemDecoration(Utils.dpToPx(8)));

Here is my SpaceItemDecoration class:

private class SpacesItemDecoration extends RecyclerView.ItemDecoration {
        private int space;

        public SpacesItemDecoration(int space) {
            this.space = space;
        }

        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            int position = parent.getChildAdapterPosition(view);
            int viewType = adapter.getItemViewType(position);
            if (viewType == 1) {
                //this is the regular view type
                if (map.get(position)) {
                    //it is on the left side
                    outRect.right = space / 2;
                    outRect.left = Utils.dpToPx(12);
                    outRect.top = space / 2;
                    outRect.bottom = space / 2;
                } else {
                    //it is on the right side
                    outRect.right = Utils.dpToPx(12);
                    outRect.left = space / 2;
                    outRect.top = space / 2;
                    outRect.bottom = space / 2;
                }
            } else {
                outRect.left = 0;
                outRect.right = 0;
                outRect.top = 0;
                outRect.bottom = 0;
            }
        }
}

Basically, I check if the item is of type section/header or is it a regular item that has to be shown in 2 columns. Further, I need to know if the regular item will be shown on the left side or right side.

Here is my method to calculate if the element will be shown on left side or right side:

private void prepareMapping(int start, int end) {
        LogUtil.i(TAG, "prepareMapping called");

//        LogUtil.i(TAG, "mapping from " + start + " to " + end);
        int lastHeaderPosition = -1;
        FeedItems currentItem;
        for (int i=start; i<end-1; i++) {
            currentItem = list.get(i);
            if (currentItem.getType() == 0) {
                //it is header
                lastHeaderPosition = i;
            } else if ((currentItem.getType() == 1) && ((i - lastHeaderPosition) % 2 == 0)) {
                //it is right side, put false into map
//                LogUtil.i(TAG, i + " is on right");
                map.put(i, false);
            } else if ((currentItem.getType() == 1) && ((i - lastHeaderPosition) % 2 != 0)) {
                //it is left side, put true into map
//                LogUtil.i(TAG, i + " is on right");
                map.put(i, true);
            }
        }
    }

So, according to my calculations, some element should come on left while other on right if the elements in the RecyclerView appear in the order in which they are in the list as coming from the backend. But, this GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS strategy shuffles my order of items and hence my left-right calculations do not hold and I get weird spacings.

To fix this, I set the gap handling strategy to GAP_HANDLING_NONE and now the RecyclerView does not show any item. Why is this happening and how can I fix this?

Amit Tiwari
  • 3,684
  • 6
  • 33
  • 75

0 Answers0