如何使用GridLayoutManager与RecyclerView设置列间距? 在我的布局中设置空白/填充没有效果。
当前回答
对于任何像我一样,想要最好的答案,但在kotlin,这里是:
class GridItemDecoration(
val spacing: Int,
private val spanCount: Int,
private val includeEdge: Boolean
) :
RecyclerView.ItemDecoration() {
/**
* Applies padding to all sides of the [Rect], which is the container for the view
*/
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
val position = parent.getChildAdapterPosition(view) // item position
val 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
}
}
}
}
如果你想从dimensions .xml中获取数字,然后将其转换为原始像素,你可以使用getDimensionPixelOffset简单地做到这一点,就像这样:
recyclerView.addItemDecoration(
GridItemDecoration(
resources.getDimensionPixelOffset(R.dimen.h1),
3,
true
)
)
其他回答
只有一个简单的解决方案,您可以记住并在任何需要的地方实施。没有bug,没有疯狂的计算。在卡片/物品布局中放置空白,并在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"/>
更新:
上面的回答已经阐明了设置边缘处理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();
}
}
对于那些有问题的staggeredLayoutManager(如https://imgur.com/XVutH5u)
recyclerView的方法:
getChildAdapterPosition(view)
getChildLayoutPosition(view)
有时返回-1作为索引,所以我们可能会遇到设置itemDecor的麻烦。我的解决方案是覆盖已弃用的ItemDecoration的方法:
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent)
而不是新手:
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state)
是这样的:
recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
@Override
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
TheAdapter.VH vh = (TheAdapter.VH) recyclerView.findViewHolderForAdapterPosition(itemPosition);
View itemView = vh.itemView; //itemView is the base view of viewHolder
//or instead of the 2 lines above maybe it's possible to use View itemView = layoutManager.findViewByPosition(itemPosition) ... NOT TESTED
StaggeredGridLayoutManager.LayoutParams itemLayoutParams = (StaggeredGridLayoutManager.LayoutParams) itemView.getLayoutParams();
int spanIndex = itemLayoutParams.getSpanIndex();
if (spanIndex == 0)
...
else
...
}
});
到目前为止似乎对我有用:)
我根据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
}
}
这是我对SpacesItemDecoration的修改,它可以在顶部,底部,左边和右边同样采取numofcolumns和空间。
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;
}*/
}
}
并在逻辑上使用下面的代码。
recyclerView.addItemDecoration(new SpacesItemDecoration(spacingInPixels, numCol));
推荐文章
- 警告:API ' variable . getjavacompile()'已过时,已被' variable . getjavacompileprovider()'取代
- 安装APK时出现错误
- 碎片中的onCreateOptionsMenu
- TextView粗体通过XML文件?
- 如何使线性布局的孩子之间的空间?
- DSL元素android.dataBinding。enabled'已过时,已被'android.buildFeatures.dataBinding'取代
- ConstraintLayout:以编程方式更改约束
- PANIC: AVD系统路径损坏。检查ANDROID_SDK_ROOT值
- 如何生成字符串类型的buildConfigField
- Recyclerview不调用onCreateViewHolder
- Android API 21工具栏填充
- Android L中不支持操作栏导航模式
- 如何在TextView中添加一个子弹符号?
- PreferenceManager getDefaultSharedPreferences在Android Q中已弃用
- 在Android Studio中创建aar文件