This is a follow-up to my previous question.
In my app I'm trying to have an horizontal RecyclerView
that automatically snaps to the center item. To do so, I've attached a LinearSnapHelper
to it. I've also created an item decoration that adds some left/right padding to the first/last element:
public class OffsetItemDecoration extends RecyclerView.ItemDecoration {
private Context ctx;
public OffsetItemDecoration(Context ctx){
this.ctx = ctx;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int nCols = ActivityUtils.getNumCols(ctx);
int colWidth = (int)(getScreenWidth()/(float)(nCols));
if(parent.getChildAdapterPosition(view) == 0){
int offset = Math.round(getScreenWidth() / 2f - colWidth / 2f);
setupOutRect(outRect, offset, true);
}
else if (parent.getChildAdapterPosition(view) == state.getItemCount()-1){
int offset = Math.round(getScreenWidth() / 2f - colWidth / 2f);
setupOutRect(outRect, offset, false);
}
}
private void setupOutRect(Rect rect, int offset, boolean start){
if(start) rect.left = offset;
else rect.right = offset;
}
private int getScreenWidth(){
WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
return size.x;
}
}
The problem is that when the RecyclerView
is populated the first time, the first item is centered in the screen and also selected, but when I try to horizontally scroll and I go back to the first item, the leftmost item I can select is the 2nd one (position 1
). The same happens for the last item, the rightmost item that can be snapped to is the penultimate one. (state.getItemCount() - 2
).
Do I need to implement a new SnapHelper
or am I doing something wrong?
RecyclerView
has own rules about ItemDecoration
. He thinks about them as a part of the item itself. You can think, what your decoration
(even if it's just a padding
) is part of your my_item.xml
itself.
LinearSnapHelper
uses methods like LayoutManager.getDecoratedMeasuredWidth()
to determine center of the view. And that's from where the problem occurs. It sees your first item much larger than you think, so it's center for the first view is acutally in (padding + view.getWidth()) / 2
. It is much farther than center for the second view, which is normal view.getX() + view.getWidth() / 2
.
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