Android -Recycler查看网格中项目之间的间距

pvabu6sv  于 2022-11-03  发布在  Android
关注(0)|答案(5)|浏览(164)

在我的Android应用程序中,我使用RecyclerView在网格中显示项目。在GridView中,为了指定元素之间的间距,我将设置horizontalSpacingverticalSpacing属性。
那么,如何在RecyclerView上实现同样的功能呢?

klh5stk1

klh5stk11#

我还没有用GridLayout测试过它,但是对于LinearLayout,我只是简单地为每个列表项的根布局设置了一个边距。我想如果你想在所有项之间保持相同的间距(比如8dp),你就必须这样做:
1.将layout_padding 4 dp设置为循环视图。
1.将layout_margin 4 dp设置为每个列表项。
这样,每个项目周围都有一个恒定的8 dp。
下面的代码是一个水平的RecyclerView,它以8 dp的正确间距显示图像:
第一个
编辑:我意识到项目视图需要有一个父视图组,所以我更新了代码片段。

n53p2ov0

n53p2ov02#

您必须使用ItemDecorator来执行以下操作:
就像这样:

public class EqualSpaceItemDecoration extends RecyclerView.ItemDecoration {

    private final int mSpaceHeight;

    public EqualSpaceItemDecoration(int mSpaceHeight) {
        this.mSpaceHeight = mSpaceHeight;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
                               RecyclerView.State state) {
        outRect.bottom = mSpaceHeight;
        outRect.top = mSpaceHeight;
        outRect.left = mSpaceHeight;
        outRect.right = mSpaceHeight;
    }
}
xienkqul

xienkqul3#

public class EqualSpaceItemDecoration extends RecyclerView.ItemDecoration {

private final int mSpaceHeight;

public EqualSpaceItemDecoration(int mSpaceHeight) {
    this.mSpaceHeight = mSpaceHeight;
}

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
        RecyclerView.State state) {
    outRect.bottom = mSpaceHeight;
outRect.top = mSpaceHeight;
outRect.left = mSpaceHeight;
outRect.right = mSpaceHeight;
}

上述答案将在图像相交处产生不相等的边距宽度。
下面的解决方案可产生均匀的利润

public void getItemOffsets (Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {        
        int position= parent.getChildAdapterPosition (view);
        int column = position% numberOfColumns;       
            outRect.left= margin-column*spacingPx/numberOfColumns;
            outRect.right= (column+1)* margin/numberOfColumns;
            outRect.top= margin;           

        }

    }
798qvoo8

798qvoo84#

RecyclerView中,可以使用ItemDecoration添加项目之间的间距。在此之前,让我们做一些数学运算来找出列表项目周围的边距。
这里我们得到了等间距的区域。在每个区域中,我们必须找到它们的边距,并在outRect中返回它。要等间距和等大小,如果你计算正确,你会发现这些偏移值不是常数,它们会根据它们的列索引和行索引而改变。让我们推导偏移值的公式。

带外边缘

在第一种情况下,我们考虑边缘周围的边距。

For 0 and 1,
d + w + a = d − a + w + c
c = 2a

For 0 and 2,
d + w + a = d − c + w + e
e = a + c
e = 3a

If you see the pattern here,
right = a, 2a, 3a, ... , (n + 1) × a
right = (nᵢ + 1) × a

na = d
a = d ÷ n
right = (nᵢ + 1) × d ÷ n

Pattern of left side,
left = d, d − a, d − 2a, d − 3a, ... , d − na
left = d − nᵢ × a
left = d − nᵢ × d ÷ n

nᵢ - Column index

无外缘

在这里,我们在不考虑边的情况下计算。

For 0 and 1,
w + a = d − a + w + c
c = 2a − d

For 0 and 2,
w + a = d − c + w + e
e = 3a − 2d

The pattern here is,
right = a, 2a − d, 3a − 2d, ... , (n + 1) × a - nd
right = (nᵢ + 1) × a - nᵢd

(n + 1) × a − nd = 0
a = nd ÷ (n + 1)

∴ right = d − d × (nᵢ + 1) ÷ q
q = n + 1
q - Column count
nᵢ - Column index

left = 0, d − a, 2(d − a), ... , n(d − a)
left = nᵢ(d − a)
left = nᵢ × d ÷ q

让我们编写代码...

class SpacingItemDecoration(
    private val spacing: Int,
    private val includeEdge: Boolean,
    private val headerRowCount: Int = 0
) : RecyclerView.ItemDecoration() {

    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        val columnCount = getColumnCount(parent)
        val position = parent.getChildAdapterPosition(view) - headerRowCount * columnCount
        if (position >= 0) {
            val rowCount = getRowCount(parent, columnCount)
            val orientation = getOrientation(parent)
            val columnIndex = position % columnCount
            val rowIndex = position / columnCount
            if (includeEdge) {
                when (orientation) {
                    RecyclerView.VERTICAL -> {
                        outRect.left = getStartOffsetWithEdge(spacing, columnIndex, columnCount)
                        outRect.right = getEndOffsetWithEdge(spacing, columnIndex, columnCount)
                        outRect.top = getStartOffsetWithEdge(spacing, rowIndex, rowCount)
                        outRect.bottom = getEndOffsetWithEdge(spacing, rowIndex, rowCount)
                    }
                    RecyclerView.HORIZONTAL -> {
                        outRect.top = getStartOffsetWithEdge(spacing, columnIndex, columnCount)
                        outRect.bottom = getEndOffsetWithEdge(spacing, columnIndex, columnCount)
                        outRect.left = getStartOffsetWithEdge(spacing, rowIndex, rowCount)
                        outRect.right = getEndOffsetWithEdge(spacing, rowIndex, rowCount)
                    }
                }
            } else {
                when (orientation) {
                    RecyclerView.VERTICAL -> {
                        outRect.left = getStartOffsetWithoutEdge(spacing, columnIndex, columnCount)
                        outRect.right = getEndOffsetWithoutEdge(spacing, columnIndex, columnCount)
                        outRect.top = getStartOffsetWithoutEdge(spacing, rowIndex, rowCount)
                        outRect.bottom = getEndOffsetWithoutEdge(spacing, rowIndex, rowCount)
                    }
                    RecyclerView.HORIZONTAL -> {
                        outRect.top = getStartOffsetWithoutEdge(spacing, columnIndex, columnCount)
                        outRect.bottom = getEndOffsetWithoutEdge(spacing, columnIndex, columnCount)
                        outRect.left = getStartOffsetWithoutEdge(spacing, rowIndex, rowCount)
                        outRect.right = getEndOffsetWithoutEdge(spacing, rowIndex, rowCount)
                    }
                }
            }
        } else {
            outRect.left = 0
            outRect.right = 0
            outRect.top = 0
            outRect.bottom = 0
        }
    }

    private fun getColumnCount(parent: RecyclerView) = when (val layoutManager = parent.layoutManager) {
        is GridLayoutManager -> layoutManager.spanCount
        is StaggeredGridLayoutManager -> layoutManager.spanCount
        else -> 1
    }

    private fun getRowCount(parent: RecyclerView, columnCount: Int) =
        parent.adapter?.itemCount?.div(columnCount)?.minus(headerRowCount)

    private fun getOrientation(parent: RecyclerView) = when (val layoutManager = parent.layoutManager) {
        is LinearLayoutManager -> layoutManager.orientation
        is GridLayoutManager -> layoutManager.orientation
        is StaggeredGridLayoutManager -> layoutManager.orientation
        else -> RecyclerView.VERTICAL
    }

    private fun getStartOffsetWithEdge(spacing: Int, columnIndex: Int, columnCount: Int?): Int {
        if (columnCount == null) return spacing
        return spacing - spacing * columnIndex / columnCount
    }

    private fun getEndOffsetWithEdge(spacing: Int, columnIndex: Int, columnCount: Int?): Int {
        if (columnCount == null) return 0
        return spacing * (columnIndex + 1) / columnCount
    }

    private fun getStartOffsetWithoutEdge(spacing: Int, columnIndex: Int, columnCount: Int?): Int {
        if (columnCount == null) return 0
        return spacing * columnIndex / columnCount
    }

    private fun getEndOffsetWithoutEdge(spacing: Int, columnIndex: Int, columnCount: Int?): Int {
        if (columnCount == null) return spacing
        return spacing - spacing * (columnIndex + 1) / columnCount
    }

}
6gpjuf90

6gpjuf905#

您可以在回收器视图中使用addItemDecoration方法。
项装饰类文件:-

class ItemDecoration(space: Int) : RecyclerView.ItemDecoration() {
      private val halfSpace: Int
      override fun getItemOffsets(outRect: Rect,
                            view: View,
                            parent: RecyclerView,
                            state: RecyclerView.State) {
             if (parent.paddingLeft != halfSpace) {
                parent.setPadding(halfSpace, halfSpace, halfSpace, halfSpace)
                parent.clipToPadding = false
             }
             outRect.top = halfSpace
             outRect.bottom = halfSpace
             outRect.left = halfSpace
             outRect.right = halfSpace
    }

    init {
       halfSpace = space / 2
    }
}

在回收视图中实现:

rvFeeds.apply {
            layoutManager = mLM
            adapter = mAdapter
            itemAnimator = null
            addItemDecoration(ItemDecoration(resources.getDimension(R.dimen.margin_very_small).toInt())) 
}

相关问题