Android Recyclerview GridLayoutManager列间距

如何使用GridLayoutManager设置RecyclerView的列间距? 在布局中设置边距/填充没有效果。

RecyclerViews支持ItemDecoration的概念:特殊的偏移和绘制每个元素。 正如在这个答案中看到的,你可以使用

 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 item to avoid double space between items if (parent.getChildLayoutPosition(view) == 0) { outRect.top = space; } else { outRect.top = 0; } } } 

然后通过添加它

 mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view); int spacingInPixels = getResources().getDimensionPixelSize(R.dimen.spacing); mRecyclerView.addItemDecoration(new SpacesItemDecoration(spacingInPixels)); 

以下代码运行良好,每列有相同的宽度:

 public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration { private int spanCount; private int spacing; private boolean includeEdge; public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) { this.spanCount = spanCount; this.spacing = spacing; this.includeEdge = includeEdge; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { int position = parent.getChildAdapterPosition(view); // item position int column = position % spanCount; // item column if (includeEdge) { outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing) outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing) if (position < spanCount) { // top edge outRect.top = spacing; } outRect.bottom = spacing; // item bottom } else { outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing) outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing) if (position >= spanCount) { outRect.top = spacing; // item top } } } } 

用法

没有边缘

在这里输入图像说明

 int spanCount = 3; // 3 columns int spacing = 50; // 50px boolean includeEdge = false; recyclerView.addItemDecoration(new GridSpacingItemDecoration(spanCount, spacing, includeEdge)); 

2.与边缘

在这里输入图像说明

 int spanCount = 3; // 3 columns int spacing = 50; // 50px boolean includeEdge = true; recyclerView.addItemDecoration(new GridSpacingItemDecoration(spanCount, spacing, includeEdge)); 

以下是一步一步简单的解决scheme,如果你想要项目和相同的项目大小相等的间距。

ItemOffsetDecoration

 public class ItemOffsetDecoration extends RecyclerView.ItemDecoration { private int mItemOffset; public ItemOffsetDecoration(int itemOffset) { mItemOffset = itemOffset; } public ItemOffsetDecoration(@NonNull Context context, @DimenRes int itemOffsetId) { this(context.getResources().getDimensionPixelSize(itemOffsetId)); } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); outRect.set(mItemOffset, mItemOffset, mItemOffset, mItemOffset); } } 

履行

在您的源代码中,将ItemOffsetDecoration添加到您的RecyclerView. 项目偏移值应该是要作为项目之间的空间添加的实际值的一半大小。

 mRecyclerView.setLayoutManager(new GridLayoutManager(context, NUM_COLUMNS); ItemOffsetDecoration itemDecoration = new ItemOffsetDecoration(context, R.dimen.item_offset); mRecyclerView.addItemDecoration(itemDecoration); 

此外,将其项目偏移值设置为其RecyclerView填充,并指定android:clipToPadding=false

 <android.support.v7.widget.RecyclerView android:id="@+id/recyclerview_grid" android:layout_width="match_parent" android:layout_height="match_parent" android:clipToPadding="false" android:padding="@dimen/item_offset"/> 

尝试这个。 它会照顾周围的等距。 与List,Grid和StaggeredGrid一起工作。

编辑

更新后的代码应该处理大多数具有跨度,方向等的angular落案例。注意,如果在GridLayoutManager中使用setSpanSizeLookup(),则出于性能原因build议使用setSpanIndexCacheEnabled()。

请注意,StaggeredGrid似乎有一个错误,其中的孩子的索引变得古怪和难以跟踪,所以下面的代码可能无法很好地与StaggeredGridLayoutManager。

 public class ListSpacingDecoration extends RecyclerView.ItemDecoration { private static final int VERTICAL = OrientationHelper.VERTICAL; private int orientation = -1; private int spanCount = -1; private int spacing; private int halfSpacing; public ListSpacingDecoration(Context context, @DimenRes int spacingDimen) { spacing = context.getResources().getDimensionPixelSize(spacingDimen); halfSpacing = spacing / 2; } public ListSpacingDecoration(int spacingPx) { spacing = spacingPx; halfSpacing = spacing / 2; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); if (orientation == -1) { orientation = getOrientation(parent); } if (spanCount == -1) { spanCount = getTotalSpan(parent); } int childCount = parent.getLayoutManager().getItemCount(); int childIndex = parent.getChildAdapterPosition(view); int itemSpanSize = getItemSpanSize(parent, childIndex); int spanIndex = getItemSpanIndex(parent, childIndex); /* INVALID SPAN */ if (spanCount < 1) return; setSpacings(outRect, parent, childCount, childIndex, itemSpanSize, spanIndex); } protected void setSpacings(Rect outRect, RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) { outRect.top = halfSpacing; outRect.bottom = halfSpacing; outRect.left = halfSpacing; outRect.right = halfSpacing; if (isTopEdge(parent, childCount, childIndex, itemSpanSize, spanIndex)) { outRect.top = spacing; } if (isLeftEdge(parent, childCount, childIndex, itemSpanSize, spanIndex)) { outRect.left = spacing; } if (isRightEdge(parent, childCount, childIndex, itemSpanSize, spanIndex)) { outRect.right = spacing; } if (isBottomEdge(parent, childCount, childIndex, itemSpanSize, spanIndex)) { outRect.bottom = spacing; } } @SuppressWarnings("all") protected int getTotalSpan(RecyclerView parent) { RecyclerView.LayoutManager mgr = parent.getLayoutManager(); if (mgr instanceof GridLayoutManager) { return ((GridLayoutManager) mgr).getSpanCount(); } else if (mgr instanceof StaggeredGridLayoutManager) { return ((StaggeredGridLayoutManager) mgr).getSpanCount(); } else if (mgr instanceof LinearLayoutManager) { return 1; } return -1; } @SuppressWarnings("all") protected int getItemSpanSize(RecyclerView parent, int childIndex) { RecyclerView.LayoutManager mgr = parent.getLayoutManager(); if (mgr instanceof GridLayoutManager) { return ((GridLayoutManager) mgr).getSpanSizeLookup().getSpanSize(childIndex); } else if (mgr instanceof StaggeredGridLayoutManager) { return 1; } else if (mgr instanceof LinearLayoutManager) { return 1; } return -1; } @SuppressWarnings("all") protected int getItemSpanIndex(RecyclerView parent, int childIndex) { RecyclerView.LayoutManager mgr = parent.getLayoutManager(); if (mgr instanceof GridLayoutManager) { return ((GridLayoutManager) mgr).getSpanSizeLookup().getSpanIndex(childIndex, spanCount); } else if (mgr instanceof StaggeredGridLayoutManager) { return childIndex % spanCount; } else if (mgr instanceof LinearLayoutManager) { return 0; } return -1; } @SuppressWarnings("all") protected int getOrientation(RecyclerView parent) { RecyclerView.LayoutManager mgr = parent.getLayoutManager(); if (mgr instanceof LinearLayoutManager) { return ((LinearLayoutManager) mgr).getOrientation(); } else if (mgr instanceof GridLayoutManager) { return ((GridLayoutManager) mgr).getOrientation(); } else if (mgr instanceof StaggeredGridLayoutManager) { return ((StaggeredGridLayoutManager) mgr).getOrientation(); } return VERTICAL; } protected boolean isLeftEdge(RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) { if (orientation == VERTICAL) { return spanIndex == 0; } else { return (childIndex == 0) || isFirstItemEdgeValid((childIndex < spanCount), parent, childIndex); } } protected boolean isRightEdge(RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) { if (orientation == VERTICAL) { return (spanIndex + itemSpanSize) == spanCount; } else { return isLastItemEdgeValid((childIndex >= childCount - spanCount), parent, childCount, childIndex, spanIndex); } } protected boolean isTopEdge(RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) { if (orientation == VERTICAL) { return (childIndex == 0) || isFirstItemEdgeValid((childIndex < spanCount), parent, childIndex); } else { return spanIndex == 0; } } protected boolean isBottomEdge(RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) { if (orientation == VERTICAL) { return isLastItemEdgeValid((childIndex >= childCount - spanCount), parent, childCount, childIndex, spanIndex); } else { return (spanIndex + itemSpanSize) == spanCount; } } protected boolean isFirstItemEdgeValid(boolean isOneOfFirstItems, RecyclerView parent, int childIndex) { int totalSpanArea = 0; if (isOneOfFirstItems) { for (int i = childIndex; i >= 0; i--) { totalSpanArea = totalSpanArea + getItemSpanSize(parent, i); } } return isOneOfFirstItems && totalSpanArea <= spanCount; } protected boolean isLastItemEdgeValid(boolean isOneOfLastItems, RecyclerView parent, int childCount, int childIndex, int spanIndex) { int totalSpanRemaining = 0; if (isOneOfLastItems) { for (int i = childIndex; i < childCount; i++) { totalSpanRemaining = totalSpanRemaining + getItemSpanSize(parent, i); } } return isOneOfLastItems && (totalSpanRemaining <= spanCount - spanIndex); } } 

希望能帮助到你。

以下代码将处理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; } } 

然后使用它

 mRecyclerView.addItemDecoration(new SpacesItemDecoration(mMargin)); 

这是一个不需要“spanCount” (列数)的解决scheme,因为我使用GridAutofitLayoutManager (根据所需的单元格大小计算列数)

(注意,这只会在GridLayoutManager上工作)

 public class GridSpacesItemDecoration extends RecyclerView.ItemDecoration { private final boolean includeEdge; private int spacing; public GridSpacesItemDecoration(int spacing, boolean includeEdge) { this.spacing = spacing; this.includeEdge = includeEdge; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (parent.getLayoutManager() instanceof GridLayoutManager) { GridLayoutManager layoutManager = (GridLayoutManager)parent.getLayoutManager(); int spanCount = layoutManager.getSpanCount(); int position = parent.getChildAdapterPosition(view); // item position int column = position % spanCount; // item column if (includeEdge) { outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing) outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing) if (position < spanCount) { // top edge outRect.top = spacing; } outRect.bottom = spacing; // item bottom } else { outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing) outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing) if (position >= spanCount) { outRect.top = spacing; // item top } } } } } 

这里是GridAutofitLayoutManager是任何人感兴趣的:

 public class GridAutofitLayoutManager extends GridLayoutManager { private int mColumnWidth; private boolean mColumnWidthChanged = true; public GridAutofitLayoutManager(Context context, int columnWidth) { /* Initially set spanCount to 1, will be changed automatically later. */ super(context, 1); setColumnWidth(checkedColumnWidth(context, columnWidth)); } public GridAutofitLayoutManager(Context context,int unit, int columnWidth) { /* Initially set spanCount to 1, will be changed automatically later. */ super(context, 1); int pixColumnWidth = (int) TypedValue.applyDimension(unit, columnWidth, context.getResources().getDisplayMetrics()); setColumnWidth(checkedColumnWidth(context, pixColumnWidth)); } public GridAutofitLayoutManager(Context context, int columnWidth, int orientation, boolean reverseLayout) { /* Initially set spanCount to 1, will be changed automatically later. */ super(context, 1, orientation, reverseLayout); setColumnWidth(checkedColumnWidth(context, columnWidth)); } private int checkedColumnWidth(Context context, int columnWidth) { if (columnWidth <= 0) { /* Set default columnWidth value (48dp here). It is better to move this constant to static constant on top, but we need context to convert it to dp, so can't really do so. */ columnWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48, context.getResources().getDisplayMetrics()); } return columnWidth; } public void setColumnWidth(int newColumnWidth) { if (newColumnWidth > 0 && newColumnWidth != mColumnWidth) { mColumnWidth = newColumnWidth; mColumnWidthChanged = true; } } @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { int width = getWidth(); int height = getHeight(); if (mColumnWidthChanged && mColumnWidth > 0 && width > 0 && height > 0) { int totalSpace; if (getOrientation() == VERTICAL) { totalSpace = width - getPaddingRight() - getPaddingLeft(); } else { totalSpace = height - getPaddingTop() - getPaddingBottom(); } int spanCount = Math.max(1, totalSpace / mColumnWidth); setSpanCount(spanCount); mColumnWidthChanged = false; } super.onLayoutChildren(recycler, state); } } 

最后:

 mDevicePhotosView.setLayoutManager(new GridAutofitLayoutManager(getContext(), getResources().getDimensionPixelSize(R.dimen.item_size))); mDevicePhotosView.addItemDecoration(new GridSpacesItemDecoration(Util.dpToPx(getContext(), 2),true)); 

上面的答案澄清了设置边距处理GridLayoutManager和LinearLayoutManager的方法。

但是对于StaggeredGridLayoutManager,Pirdad Sakhizada的答案是:“StaggeredGridLayoutManager可能不能很好地工作”。 这应该是关于IndexOfSpan的问题。

你可以通过这种方式得到它:

 private static class MyItemDecoration extends RecyclerView.ItemDecoration { @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); int index = ((StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex(); } } 

复制@edwardaa提供的代码,我使它完美支持RTL:

 public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration { private int spanCount; private int spacing; private boolean includeEdge; private int headerNum; private boolean isRtl = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL; public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge, int headerNum) { this.spanCount = spanCount; this.spacing = spacing; this.includeEdge = includeEdge; this.headerNum = headerNum; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { int position = parent.getChildAdapterPosition(view) - headerNum; // item position if (position >= 0) { int column = position % spanCount; // item column if(isRtl) { column = spanCount - 1 - column; } if (includeEdge) { outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing) outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing) if (position < spanCount) { // top edge outRect.top = spacing; } outRect.bottom = spacing; // item bottom } else { outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing) outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing) if (position >= spanCount) { outRect.top = spacing; // item top } } } else { outRect.left = 0; outRect.right = 0; outRect.top = 0; outRect.bottom = 0; } } } 
 Here is my modification of SpacesItemDecoration which can take numOfColums and space equally on top,bottom,left and right. public class SpacesItemDecoration extends RecyclerView.ItemDecoration { private int space; private int mNumCol; public SpacesItemDecoration(int space, int numCol) { this.space = space; this.mNumCol=numCol; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { //outRect.right = space; outRect.bottom = space; //outRect.left = space; //Log.d("ttt", "item position" + parent.getChildLayoutPosition(view)); int position=parent.getChildLayoutPosition(view); if(mNumCol<=2) { if (position == 0) { outRect.left = space; outRect.right = space / 2; } else { if ((position % mNumCol) != 0) { outRect.left = space / 2; outRect.right = space; } else { outRect.left = space; outRect.right = space / 2; } } }else{ if (position == 0) { outRect.left = space; outRect.right = space / 2; } else { if ((position % mNumCol) == 0) { outRect.left = space; outRect.right = space/2; } else if((position % mNumCol) == (mNumCol-1)){ outRect.left = space/2; outRect.right = space; }else{ outRect.left=space/2; outRect.right=space/2; } } } if(position<mNumCol){ outRect.top=space; }else{ outRect.top=0; } // Add top margin only for the first item to avoid double space between items /* if (parent.getChildLayoutPosition(view) == 0 ) { } else { outRect.top = 0; }*/ } } and use below code on your logic. recyclerView.addItemDecoration(new SpacesItemDecoration(spacingInPixels, numCol)); 

这个问题有一个非常简单而又灵活的解决scheme,只使用在每个LayoutManager上工作的XML。

假设你想要X的等间距(例如8dp)。

1将您的CardView项目包裹在另一个布局中

2-为外部布局提供X / 2(4dp)的填充

3-使外部布局背景透明

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="200dp" android:layout_height="200dp" android:background="@android:color/transparent" android:padding="4dip"> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v7.widget.CardView> </LinearLayout> 

4 – 给你的RecyclerView填充X / 2(4dp)

  <android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" android:padding="4dp" /> 

这就是它。 你有完美的X(8dp)的间距。

 public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration { private int spanCount; private int spacing; private boolean includeEdge; public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) { this.spanCount = spanCount; this.spacing = spacing; this.includeEdge = includeEdge; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams(); int column = params.getSpanIndex(); if (includeEdge) { outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing) outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing) if (position < spanCount) { // top edge outRect.top = spacing; } outRect.bottom = spacing; // item bottom } else { outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing) outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing) if (position >= spanCount) { outRect.top = spacing; // item top } } } 

}

与edwardaa的答案有点不同,不同之处在于如何确定列,因为在诸如具有不同高度的项目的情况下,列不能简单地由%spanCount

我结束了这样做我的RecyclerView与GridLayoutManager和HeaderView

在下面的代码中,我在每个项目之间设置了一个4dp的空间(每个项目周围2dp,在整个recyclerview周围填充2dp)。

layout.xml

 <android.support.v7.widget.RecyclerView android:id="@+id/recycleview" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="2dp" /> 

片段/活动

 GridLayoutManager manager = new GridLayoutManager(getContext(), 3); recyclerView.setLayoutManager(manager); int spacingInPixels = Utils.dpToPx(2); recyclerView.addItemDecoration(new SpacesItemDecoration(spacingInPixels)); 

SpaceItemDecoration.java

 public class SpacesItemDecoration extends RecyclerView.ItemDecoration { private int mSpacing; public SpacesItemDecoration(int spacing) { mSpacing = spacing; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView recyclerView, RecyclerView.State state) { outRect.left = mSpacing; outRect.top = mSpacing; outRect.right = mSpacing; outRect.bottom = mSpacing; } } 

Utils.java

 public static int dpToPx(final float dp) { return Math.round(dp * (Resources.getSystem().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT)); } 

感谢edwardaa的回答https://stackoverflow.com/a/30701422/2227031

还有一点要注意的是:

如果总间距和总itemWidth不等于屏幕宽度,则还需要调整itemWidth,例如适配器onBindViewHolder方法

 Utils.init(_mActivity); int width = 0; if (includeEdge) { width = ScreenUtils.getScreenWidth() - spacing * (spanCount + 1); } else { width = ScreenUtils.getScreenWidth() - spacing * (spanCount - 1); } int itemWidth = width / spanCount; ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) holder.imageViewAvatar.getLayoutParams(); // suppose the width and height are the same layoutParams.width = itemWidth; layoutParams.height = itemWidth; holder.imageViewAvatar.setLayoutParams(layoutParams); 

如果您想在所有设备上固定您的RecyclerView项目的大小。 你可以这样做

 public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration { private int mSpanCount; private float mItemSize; public GridSpacingItemDecoration(int spanCount, int itemSize) { this.mSpanCount = spanCount; mItemSize = itemSize; } @Override public void getItemOffsets(final Rect outRect, final View view, RecyclerView parent, RecyclerView.State state) { final int position = parent.getChildLayoutPosition(view); final int column = position % mSpanCount; final int parentWidth = parent.getWidth(); int spacing = (int) (parentWidth - (mItemSize * mSpanCount)) / (mSpanCount + 1); outRect.left = spacing - column * spacing / mSpanCount; outRect.right = (column + 1) * spacing / mSpanCount; if (position < mSpanCount) { outRect.top = spacing; } outRect.bottom = spacing; } } 

recyclerview_item.xml

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="@dimen/recycler_view_item_width" ... > ... </LinearLayout> 

dimens.xml

  <dimen name="recycler_view_item_width">60dp</dimen> 

活动

 int numberOfColumns = 3; mRecyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns)); mRecyclerView.setAdapter(...); mRecyclerView.addItemDecoration(new GridSpacingItemDecoration(3, getResources().getDimensionPixelSize(R.dimen.recycler_view_item_width))); 

在这里输入图像说明 在这里输入图像说明

只有一个简单的解决scheme,你可以记住和实施任何需要的地方。 没有错误,没有疯狂的计算。 将保证金放入卡片/项目布局,并将填充的大小放入RecyclerView:

item_layout.xml

 <CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:margin="10dp"> 

activity_layout.xml

 <RecyclerView android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp"/> 

为了使https://stackoverflow.com/a/29905000/1649371 (上面)解决scheme工作,我不得不修改以下方法(和所有后续调用)

 @SuppressWarnings("all") protected int getItemSpanSize(RecyclerView parent, View view, int childIndex) { RecyclerView.LayoutManager mgr = parent.getLayoutManager(); if (mgr instanceof GridLayoutManager) { return ((GridLayoutManager) mgr).getSpanSizeLookup().getSpanSize(childIndex); } else if (mgr instanceof StaggeredGridLayoutManager) { return ((StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams()).isFullSpan() ? spanCount : 1; } else if (mgr instanceof LinearLayoutManager) { return 1; } return -1; } @SuppressWarnings("all") protected int getItemSpanIndex(RecyclerView parent, View view, int childIndex) { RecyclerView.LayoutManager mgr = parent.getLayoutManager(); if (mgr instanceof GridLayoutManager) { return ((GridLayoutManager) mgr).getSpanSizeLookup().getSpanIndex(childIndex, spanCount); } else if (mgr instanceof StaggeredGridLayoutManager) { return ((StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex(); } else if (mgr instanceof LinearLayoutManager) { return 0; } return -1; }