Как избежать двойного пробела между элементами при использовании RecyclerView с помощью StaggeredGridLayoutManager?

Я использую RecyclerView с StaggeredGridLayoutManager, чтобы создать список из двух столбцов. Но как установить правое поле между левым столбцом и правым столбцом. Я использовал этот код, чтобы сделать правильный край сверху, но как решить двойное пространство между столбцами.

public class SpacesItemDecoration extends RecyclerView.ItemDecoration { private int space; public SpacesItemDecoration(int space) { this.space = space; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { outRect.left = space; outRect.right = space; outRect.bottom = space; // Add top margin only for the first or second item to avoid double space between items // Add top margin only for the first or second item to avoid double space between items if((parent.getChildCount() > 0 && parent.getChildPosition(view) == 0) || (parent.getChildCount() > 1 && parent.getChildPosition(view) == 1)) outRect.top = space; } 

И в действии:

 recyclerView.addItemDecoration(new SpacesItemDecoration(20)); 

Я попытался использовать view.getX() , он всегда возвращает 0.

Может кто-нибудь мне помочь? Большое спасибо!

Solutions Collecting From Web of "Как избежать двойного пробела между элементами при использовании RecyclerView с помощью StaggeredGridLayoutManager?"

В вашем случае вы можете установить оба поля в RecyclerView. Но в моем случае изображение соответствует ширине экрана в RecyclerView, и я использую ItemDecoration для решения проблемы.

  class ViewItemDecoration extends RecyclerView.ItemDecoration { public ViewItemDecoration() { } @Override public void getItemOffsets(Rect outRect, final View view, final RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); int position = parent.getChildAdapterPosition(view); int spanIndex = ((StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex(); int type = adapter.getItemViewType(position); switch(type){ case YOUR_ITEMS: if (spanIndex == 0) { outRect.left = 10; outRect.right = 5; } else {//if you just have 2 span . Or you can use (staggeredGridLayoutManager.getSpanCount()-1) as last span outRect.left = 5; outRect.right = 10; } } } } 

Следующий код будет обрабатывать StaggeredGridLayoutManager, GridLayoutManager и LinearLayoutManager.

 public class SpacesItemDecoration extends RecyclerView.ItemDecoration { private int halfSpace; public SpacesItemDecoration(int space) { this.halfSpace = space / 2; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (parent.getPaddingLeft() != halfSpace) { parent.setPadding(halfSpace, halfSpace, halfSpace, halfSpace); parent.setClipToPadding(false); } outRect.top = halfSpace; outRect.bottom = halfSpace; outRect.left = halfSpace; outRect.right = halfSpace; } } 

Я решил это самостоятельно, установив маржу позиции и дополнение RecyclerView. Оба поля и отступы – половина ожидаемого пространства, поэтому проблема исчезла.

Задайте другое левое / правое пространство в ItemDecoration в соответствии с spanindex, только хорошо работает для элемента с фиксированным размером. Если в представлении элемента есть представление изображения, установленное wrap_content по высоте, представление элемента может изменить позицию диапазона, но индекс диапазона не обновляется по вашему желанию, маржа будет беспорядочной.

Мой способ – использовать симметричное левое / правое пространство для элемента вида.

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // init recyclerView = (RecyclerView) rv.findViewById(R.id.img_waterfall); layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(new MyAdapter(getContext())); recyclerView.addItemDecoration(new SpacesItemDecoration( getResources().getDimensionPixelSize(R.dimen.space))); } private static class SpacesItemDecoration extends RecyclerView.ItemDecoration { private final int space; public SpacesItemDecoration(int space) { this.space = space; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { outRect.bottom = 2 * space; int pos = parent.getChildAdapterPosition(view); outRect.left = space; outRect.right = space; if (pos < 2) outRect.top = 2 * space; } } 

Затем установите одинаковое дополнение для RecylerView (слева / справа) android: paddingLeft = "@ dimen / space" android: paddingRight = "@ dimen / space"

  <android.support.v7.widget.RecyclerView android:id="@+id/img_waterfall" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/space" android:paddingRight="@dimen/space"/> 

Я бы слегка изменил и изменил оба ответа для относительного вопроса

 public class SpacesItemDecoration extends RecyclerView.ItemDecoration { private final int mSpace; public SpacesItemDecoration(int space) { this.mSpace = space; } @Override public void getItemOffsets(Rect outRect, final View view, final RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); int position = parent.getChildAdapterPosition(view); int spanIndex = ((StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex(); if (spanIndex == 0) { outRect.left = 30; outRect.right = 15; } else {//if you just have 2 span . Or you can use (staggeredGridLayoutManager.getSpanCount()-1) as last span outRect.left = 15; outRect.right = 30; } outRect.bottom = 30; // Add top margin only for the first item to avoid double space between items if (parent.getChildAdapterPosition(view) == 0) { outRect.top = 30; outRect.right = 30; } } } 
 public class EqualGapItemDecoration extends RecyclerView.ItemDecoration { private int spanCount; private int spacing; public EqualGapItemDecoration(int spanCount, int spacing) { this.spanCount = spanCount; this.spacing = spacing; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams(); if (layoutParams.isFullSpan()) { outRect.set(0, 0, 0, 0); } else { int spanIndex = layoutParams.getSpanIndex(); int layoutPosition = layoutParams.getViewLayoutPosition(); int itemCount = parent.getAdapter().getItemCount(); boolean leftEdge = spanIndex == 0; boolean rightEdge = spanIndex == (spanCount - 1); boolean topEdge = spanIndex < spanCount; boolean bottomEdge = layoutPosition >= (itemCount - spanCount); int halfSpacing = spacing / 2; outRect.set( leftEdge ? spacing : halfSpacing, topEdge ? spacing : halfSpacing, rightEdge ? spacing : halfSpacing, bottomEdge ? spacing : 0 ); } } }