I've created a custom ItemDecoration for a RecyclerView that is using a GridLayoutManager. The ItemDecoration essentially ensures that equivalent spacing between all of the child views is applied within the RecyclerView:

The ItemDecoration is working exactly as I hoped it would and I think it looks great. However, I noticed that I need to add the ItemDecoration before I set the layout manager for my RecyclerView. My main question is: Why is that?
I'm working with some legacy code that uses a CursorLoader to pull RSS feeds from the web and display them to the end user. For whatever reason, the layout manager is being set in onLoadFinished():
@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
Adapter adapter = new Adapter(cursor);
adapter.setHasStableIds(true);
mRecyclerView.setAdapter(adapter);
GridLayoutManager gridLayoutManager =
new GridLayoutManager(this, mColumnCount, GridLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(gridLayoutManager);
}
I noticed that if I add my ItemDecoration within onLoadFinished(), the margins between the items looks bigger than it really should:
@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
Adapter adapter = new Adapter(cursor);
adapter.setHasStableIds(true);
mRecyclerView.setAdapter(adapter);
GridLayoutManager gridLayoutManager =
new GridLayoutManager(this, mColumnCount, GridLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(gridLayoutManager);
// Adding the custom ItemDecoration
EqualOffsetItemDecoration itemDecoration = new EqualOffsetItemDecoration(this, R.dimen.card_view_margin, mColumnCount);
mRecyclerView.addItemDecoration(itemDecoration);
}

The screenshot above shows far more margin than I was expecting since I'm only applying 8dps (the value of card_view_margin). However, if I add the ItemDecoration within onCreate(), then it appears as expected:
@Override
protected void onCreate(Bundle savedInstanceState) {
...
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mColumnCount = getResources().getInteger(R.integer.list_column_count);
/*
In order to have equal spacing along the edges of the screen as well as between the
child views of the RecyclerView, an EqualOffsetItemDecoration is applied to the RecyclerView.
*/
EqualOffsetItemDecoration itemDecoration = new EqualOffsetItemDecoration(this, R.dimen.card_view_margin, mColumnCount);
mRecyclerView.addItemDecoration(itemDecoration);
...
}
...which is the case for the first screenshot. So why does this matter? Why do I need to add the ItemDecoration before applying a layout manager to my RecyclerView? I'm sure that this has something to do with the order in which things are executed under the hood. Any sort of explanation is greatly appreciated :)
FYI, in case anyone is interested in how I created my ItemDecoration, here it is:
https://github.com/mikepalarz/XYZReader/blob/master/app/src/main/java/com/example/xyzreader/ui/EqualOffsetItemDecoration.java
Interesting question, but I don't believe it matters if you set the layout manager before or after the item decoration. Both calls result in a request for layout.
I am going to guess that you are adding the decoration to the RecyclerView more than one time. Since decorations compound, you will see a greater gap with the decoration added two times (or more times) instead of just once.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With