5

I have been trying to create a recyclerView so far, but now I am faced with a problem.

I need to make it to look like this

enter image description here

I need to make it Grid like list, however I am unable to place them side by side.

Secondly, I need the last item to fill both spaces if the last item is "alone".

Any ideas?

JayVDiyk
  • 4,277
  • 22
  • 70
  • 135

2 Answers2

2

I need to make it Grid like list

You can acheive it using RecyclerView with GridLayoutManager. For example,

// Initialize the view
recyclerView=(RecyclerView)findViewById(R.id.recyclerView);
// Here 2 is the number of columns
GridLayoutManager llm = new GridLayoutManager(this, 2);
recyclerView.setLayoutManager(llm);
recyclerView.setHasFixedSize(true);

I need the last item to fill both spaces if the last item is "alone"

To customize the grid items, we can use ItemDecoration. And in your case, the last item if it is alone should have the parent width. We can acheive this by checking the position of the last item.

Now, the code:

In Activity

recyclerView=(RecyclerView)findViewById(R.id.recyclerView);
GridLayoutManager llm = new GridLayoutManager(this, 2);
recyclerView.setLayoutManager(llm);
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(new GridItemDecoration());
// And set adapter

GridItemDecoration.java

public class GridItemDecoration extends RecyclerView.ItemDecoration
{
    private int mHorizontalSpacing = 10;
    private int mVerticalSpacing = 10;

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state)
    {
        super.getItemOffsets(outRect, view, parent, state);
        // Only handle the vertical situation
        int position = parent.getChildPosition(view);
        if (parent.getLayoutManager() instanceof GridLayoutManager)
        {
            GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager();
            int spanCount, column;
            // Check the last item and is alone. Then set the parent's width
            if (position == parent.getAdapter().getItemCount() - 1 && position % 2 == 0)
            {
                spanCount = 1;
                outRect.left = mHorizontalSpacing;
                outRect.right = parent.getWidth() - mHorizontalSpacing;
            }
            else
            {
                spanCount = layoutManager.getSpanCount();
                column = position % spanCount;
                outRect.left = mHorizontalSpacing * (spanCount - column) / spanCount;
                outRect.right = mHorizontalSpacing * (column + 1) / spanCount;
            }

            if (position < spanCount)
            {
                outRect.top = mVerticalSpacing;
            }
            outRect.bottom = mVerticalSpacing;
        }
    }
}
Faraz
  • 2,144
  • 1
  • 18
  • 28
  • Thanks but, the last item became "empty". I cannot set any text to it parent.getWidth() seems to be the culprit here – JayVDiyk Jan 19 '16 at 05:51
2

For set different span count you may use GridLayoutManager standard function setSpanSizeLookup.

This realization in Kotlin for fill screen width on last item:

// Count of columns (I set it in integer resources for screen optimisation)
val spanCount = resources.getInteger(R.integer.column_count)

val layoutManager = GridLayoutManager(context, spanCount)
layoutManager.spanSizeLookup = object : SpanSizeLookup() {
    override fun getSpanSize(position: Int): Int {
        val isLastItem = position == adapter.getItemList().lastIndex

        return if (isLastItem) {
            /**
             * Return this for full width of screen.
             * It will be always equal 1, dividing only to avoid numbers in code.
             */
            spanCount / spanCount
        } else {
            // Return this for place item in your column.
            spanCount
        }
    }
}

Also if you have complicated adapter with plenty items, you may use this realization, for example:

val spanCount = resources.getInteger(R.integer.column_count_profile)
val layoutManager = GridLayoutManager(context, spanCount)
layoutManager.spanSizeLookup = object : SpanSizeLookup() {
    override fun getSpanSize(position: Int): Int {
        val item = adapter.getItemList().getOrNull(position) ?: return spanCount
        return when (item) {
            is ScreenItem.Header -> spanCount
            is ScreenItem.Status -> spanCount
            is ScreenItem.Progress -> spanCount
            is ScreenItem.Empty -> spanCount
            is ScreenItem.Item -> spanCount / spanCount
            is ScreenItem.Load -> spanCount / spanCount
        }
    }
}

Where ScreenItem is sealed class, inside which something like this:

sealed class ScreenItem{
    object Header : ScreenItem()
    data class Status(var content: ContentItem) : ScreenItem()
    object Progress : ScreenItem()
    object Empty : ScreenItem()
    data class Item(val content: AnotherContentItem) : ScreenItem()
    object Load : ScreenItem()
}

P.S. check out this article on medium about different items in list and different column count. May be it will be helpful for someone.

SerjantArbuz
  • 982
  • 1
  • 12
  • 16