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


当前回答

对于StaggeredGridLayoutManager用户,要小心,这里有很多答案,包括投票最多的一个计算项目列,使用以下代码:

int column = position % spanCount

假设第1 /3 /5 /..物品总是放在左边和第二/第四/第六/..物品总是放在右边。这个假设总是正确的吗?不。

假设你的第一件物品是100dp高,第二件只有50dp高,猜猜你的第三件物品位于哪里,左边还是右边?

其他回答

对于这个问题,有一个非常简单而灵活的解决方案,它只使用适用于每个LayoutManager的XML。

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

在另一个布局中包装CardView项 给外层布局填充X/2 (4dp) 使外层布局背景透明

...

<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>

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

...

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

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

这就是最后对我有用的方法:

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,但我不相信有。

当为儿童使用CardView时,项目之间的空格问题可以通过设置app:cardUseCompatPadding为true来解决。

为更大的边际扩大项目抬高。CardElevation是可选的(使用默认值)。

<androidx.cardview.widget.CardView
    xmlns:app="http://schemas.android.com/apk/res-auto"
    app:cardUseCompatPadding="true"
    app:cardElevation="2dp">

如果你想在所有设备中固定你的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)));

如果你想要物品周围的间距和物品大小相等,下面是一步一步的简单解决方案。

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);

同样,设置项目偏移值为itsRecyclerView的填充,并指定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"/>