-
-
Save alexfu/f7b8278009f3119f523a to your computer and use it in GitHub Desktop.
import android.graphics.Rect; | |
import android.support.v7.widget.GridLayoutManager; | |
import android.support.v7.widget.RecyclerView; | |
import android.view.View; | |
public class EqualSpacingItemDecoration extends RecyclerView.ItemDecoration { | |
private final int spacing; | |
private int displayMode; | |
public static final int HORIZONTAL = 0; | |
public static final int VERTICAL = 1; | |
public static final int GRID = 2; | |
public EqualSpacingItemDecoration(int spacing) { | |
this(spacing, -1); | |
} | |
public EqualSpacingItemDecoration(int spacing, int displayMode) { | |
this.spacing = spacing; | |
this.displayMode = displayMode; | |
} | |
@Override | |
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { | |
int position = parent.getChildViewHolder(view).getAdapterPosition(); | |
int itemCount = state.getItemCount(); | |
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager(); | |
setSpacingForDirection(outRect, layoutManager, position, itemCount); | |
} | |
private void setSpacingForDirection(Rect outRect, | |
RecyclerView.LayoutManager layoutManager, | |
int position, | |
int itemCount) { | |
// Resolve display mode automatically | |
if (displayMode == -1) { | |
displayMode = resolveDisplayMode(layoutManager); | |
} | |
switch (displayMode) { | |
case HORIZONTAL: | |
outRect.left = spacing; | |
outRect.right = position == itemCount - 1 ? spacing : 0; | |
outRect.top = spacing; | |
outRect.bottom = spacing; | |
break; | |
case VERTICAL: | |
outRect.left = spacing; | |
outRect.right = spacing; | |
outRect.top = spacing; | |
outRect.bottom = position == itemCount - 1 ? spacing : 0; | |
break; | |
case GRID: | |
if (layoutManager instanceof GridLayoutManager) { | |
GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager; | |
int cols = gridLayoutManager.getSpanCount(); | |
int rows = itemCount / cols; | |
outRect.left = spacing; | |
outRect.right = position % cols == cols - 1 ? spacing : 0; | |
outRect.top = spacing; | |
outRect.bottom = position / cols == rows - 1 ? spacing : 0; | |
} | |
break; | |
} | |
} | |
private int resolveDisplayMode(RecyclerView.LayoutManager layoutManager) { | |
if (layoutManager instanceof GridLayoutManager) return GRID; | |
if (layoutManager.canScrollHorizontally()) return HORIZONTAL; | |
return VERTICAL; | |
} | |
} |
// Automatically infer display orientation of items | |
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview); | |
recyclerView.addItemDecoration(new EqualSpacingItemDecoration(16)); // 16px. In practice, you'll want to use getDimensionPixelSize | |
// Explicitly specify display orientation of items. | |
// Available display modes: | |
// - HORIZONTAL | |
// - VERTICAL | |
// - GRID | |
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview); | |
recyclerView.addItemDecoration(new EqualSpacingItemDecoration(16, EqualSpacingItemDecoration.HORIZONTAL)); // 16px. In practice, you'll want to use getDimensionPixelSize |
Why?
@Morphin3 Is right.
I've set span count to 2 and I'm getting extra space on the last item if item count is odd.
Put this snippet below 58,it'll work fine now.
if (itemCount % 2 == 1) {
rows = rows + 1;
}
i need to set space only right side in horizontal list. please help me
Note that the third column in the "AFTER" graphic is narrower than the first two columns. It's not that noticeable in the graphic, but in my case all my items are constrained to be square and it is very obvious.
In the end, the solution for me was:
- Set
layout_margin
of the item view to half the desired spacing between items - Set
padding
of RecyclerView, also to half the desired spacing between items - Set
clipToPadding
to false on the RecyclerView - this is very important, otherwise the padding in the previous step cuts off the edges of the scroll view.
Tada! All items are uniformly spaced and sized.
@ammojamo your code very great! thanks save my life
Note that the third column in the "AFTER" graphic is narrower than the first two columns. It's not that noticeable in the graphic, but in my case all my items are constrained to be square and it is very obvious.
In the end, the solution for me was:
- Set
layout_margin
of the item view to half the desired spacing between items- Set
padding
of RecyclerView, also to half the desired spacing between items- Set
clipToPadding
to false on the RecyclerView - this is very important, otherwise the padding in the previous step cuts off the edges of the scroll view.Tada! All items are uniformly spaced and sized.
Yes. My exact case and your solution worked like a charm. 👍
at line 58 should be:
int rows = itemCount / cols + 1;