StackOverflow contains a lot of questions like this one, but so far absolutely no solution works 100%.
I tried the solutions for these:
RecyclerView ItemDecoration - How to draw a different width divider for every viewHolder?
first item center aligns in SnapHelper in RecyclerView
Horizontally center first item of RecyclerView
LinearSnapHelper doesn't snap on edge items of RecyclerView
Android Centering Item in RecyclerView
How to make recycler view start adding items from center?
How to snap to particular position of LinearSnapHelper in horizontal RecyclerView?
And every time the first item fails to be centered correctly.
Sample code of what I am using
recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
@Override
public void getItemOffsets(
@NonNull Rect outRect,
@NonNull View view,
@NonNull RecyclerView parent,
@NonNull RecyclerView.State state
) {
super.getItemOffsets(outRect, view, parent, state);
final int count = state.getItemCount();
final int position = parent.getChildAdapterPosition(view);
if (position == 0 || position == count - 1) {
int offset = (int) (parent.getWidth() * 0.5f - view.getWidth() * 0.5f);
if (position == 0) {
setupOutRect(outRect, offset, true);
} else if (position == count - 1) {
setupOutRect(outRect, offset, false);
}
}
}
private void setupOutRect(Rect rect, int offset, boolean start) {
if (start) {
rect.left = offset;
} else {
rect.right = offset;
}
}
});
After investigating I discovered that is because at the time of the getItemOffsets
the view.getWidth
is 0, it hasn't been measured yet.
I tried to force it to be measured, but every single time it gives an incorrect size, nothing like the actual size it occupies, it is smaller.
I also tried to use the addOnGlobalLayoutListener
trick, but by the time it is called and has the correct width, the outRect
was already consumed, so it is lost.
I do not want to set any fixed sizes because the items in the RecyclerView
can have different sizes, so setting its padding in advance is not an option.
I also do not want to add "ghost" items to fill the space and those also don't work well for the scrolling experience.
How can I get this working properly?
Ideally the ItemDecorator
method looks to be the best, but it falls flat for the first item right away.