如何使用GridLayoutManager与RecyclerView设置列间距? 在我的布局中设置空白/填充没有效果。
当前回答
我最后用GridLayoutManager和HeaderView为我的RecyclerView做了这样的事情。
在下面的代码中,我在每个项目之间设置了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));
}
其他回答
如果你想在所有设备中固定你的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)));
下面的代码工作得很好,每个列都有相同的宽度:
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
}
}
}
}
使用
1. 没有优势
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));
我根据edwardaa的回答做了一个Kotlin版本
class RecyclerItemDecoration(private val spanCount: Int, private val spacing: Int) : RecyclerView.ItemDecoration() {
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
val spacing = Math.round(spacing * parent.context.resources.displayMetrics.density)
val position = parent.getChildAdapterPosition(view)
val column = position % spanCount
outRect.left = spacing - column * spacing / spanCount
outRect.right = (column + 1) * spacing / spanCount
outRect.top = if (position < spanCount) spacing else 0
outRect.bottom = spacing
}
}
这也适用于RecyclerView with header。
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {
private int spanCount;
private int spacing;
private boolean includeEdge;
private int headerNum;
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 (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;
}
}
}
}
我最后用GridLayoutManager和HeaderView为我的RecyclerView做了这样的事情。
在下面的代码中,我在每个项目之间设置了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));
}
推荐文章
- 如何隐藏动作栏之前的活动被创建,然后再显示它?
- 是否有一种方法以编程方式滚动滚动视图到特定的编辑文本?
- 在Android中将字符串转换为Uri
- 如何在NestedScrollView内使用RecyclerView ?
- 移动到另一个EditText时,软键盘下一步点击Android
- Android应用中的GridView VS GridLayout
- Activity和FragmentActivity的区别
- 右对齐文本在android TextView
- 权限拒绝:start前台需要android.permission.FOREGROUND_SERVICE
- 如何更改android操作栏的标题和图标
- Android Split字符串
- 让一个链接在安卓浏览器启动我的应用程序?
- 如何在Android工作室的外部库中添加一个jar ?
- GridLayout(不是GridView)如何均匀地拉伸所有子元素
- 如何让一个片段删除自己,即它的等效完成()?