如何使用GridLayoutManager与RecyclerView设置列间距? 在我的布局中设置空白/填充没有效果。
当前回答
确保你在gradle模块中实现了这个:
implementation 'com.github.grzegorzojdana:SpacingItemDecoration:1.1.0'
创建这个简单的函数:
public static int dpToPx(Context c, int dp) {
Resources r = c.getResources();
return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics()));
}
最后实现如下所示的空格:
photosRecycler.addItemDecoration(new SpacingItemDecoration(2, dpToPx(this, 4), true));
其他回答
这也适用于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;
}
}
}
}
确保你在gradle模块中实现了这个:
implementation 'com.github.grzegorzojdana:SpacingItemDecoration:1.1.0'
创建这个简单的函数:
public static int dpToPx(Context c, int dp) {
Resources r = c.getResources();
return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics()));
}
最后实现如下所示的空格:
photosRecycler.addItemDecoration(new SpacingItemDecoration(2, dpToPx(this, 4), true));
这就是最后对我有用的方法:
binding.rows.addItemDecoration(object: RecyclerView.ItemDecoration() {
val px = resources.getDimensionPixelSize(R.dimen.grid_spacing)
val spanCount = 2
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
val index = parent.getChildLayoutPosition(view)
val isLeft = (index % spanCount == 0)
outRect.set(
if (isLeft) px else px/2,
0,
if (isLeft) px/2 else px,
px
)
}
})
因为我只有2列(val spanCount = 2),我可以只做isLeft。如果有> 2列,那么我也需要一个isMiddle,两边的值都是px/2。
我希望有一种方法来获得应用程序:spanCount从直接从RecyclerView,但我不相信有。
上面的回答已经阐明了设置边缘处理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();
}
}
选择的答案几乎是完美的,但根据空间的不同,项目的宽度可能不相等。(对我来说,这很关键)。所以我最终用这个代码增加了一点空间,所以项目都是相同的宽度。
class GridSpacingItemDecoration(private val columnCount: Int, @Px preferredSpace: Int, private val includeEdge: Boolean): RecyclerView.ItemDecoration() {
/**
* In this algorithm space should divide by 3 without remnant or width of items can have a difference
* and we want them to be exactly the same
*/
private val space = if (preferredSpace % 3 == 0) preferredSpace else (preferredSpace + (3 - preferredSpace % 3))
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State?) {
val position = parent.getChildAdapterPosition(view)
if (includeEdge) {
when {
position % columnCount == 0 -> {
outRect.left = space
outRect.right = space / 3
}
position % columnCount == columnCount - 1 -> {
outRect.right = space
outRect.left = space / 3
}
else -> {
outRect.left = space * 2 / 3
outRect.right = space * 2 / 3
}
}
if (position < columnCount) {
outRect.top = space
}
outRect.bottom = space
} else {
when {
position % columnCount == 0 -> outRect.right = space * 2 / 3
position % columnCount == columnCount - 1 -> outRect.left = space * 2 / 3
else -> {
outRect.left = space / 3
outRect.right = space / 3
}
}
if (position >= columnCount) {
outRect.top = space
}
}
}
}
推荐文章
- 何时在Android中使用RxJava,何时使用Android架构组件中的LiveData ?
- 如何在Android项目中使用ThreeTenABP
- 指定的子节点已经有一个父节点。你必须先在子对象的父对象上调用removeView() (Android)
- 我的Android设备没有出现在adb设备列表中
- 在没有安装apk的情况下获取Android .apk文件的VersionName或VersionCode
- Fragment onResume() & onPause()不会在backstack上被调用
- 如何设置基线对齐为假提高性能在线性布局?
- 如何获得当前屏幕方向?
- 如何在Android中渲染PDF文件
- 我如何解决错误“minCompileSdk(31)指定在一个依赖的AAR元数据”在本机Java或Kotlin?
- 如何改变TextInputLayout的浮动标签颜色
- Android工作室如何运行gradle同步手动?
- 如何以编程方式在我的EditText上设置焦点(并显示键盘)
- 如果在片段和活动中同时定义,则不会在片段中调用onRequestPermissionsResult
- 方法setDrawerListener已弃用