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
}
}
5条答案
按热度按时间klh5stk11#
我还没有用GridLayout测试过它,但是对于LinearLayout,我只是简单地为每个列表项的根布局设置了一个边距。我想如果你想在所有项之间保持相同的间距(比如8dp),你就必须这样做:
1.将layout_padding 4 dp设置为循环视图。
1.将layout_margin 4 dp设置为每个列表项。
这样,每个项目周围都有一个恒定的8 dp。
下面的代码是一个水平的RecyclerView,它以8 dp的正确间距显示图像:
第一个
编辑:我意识到项目视图需要有一个父视图组,所以我更新了代码片段。
n53p2ov02#
您必须使用
ItemDecorator
来执行以下操作:就像这样:
xienkqul3#
上述答案将在图像相交处产生不相等的边距宽度。
下面的解决方案可产生均匀的利润
798qvoo84#
在
RecyclerView
中,可以使用ItemDecoration
添加项目之间的间距。在此之前,让我们做一些数学运算来找出列表项目周围的边距。这里我们得到了等间距的区域。在每个区域中,我们必须找到它们的边距,并在
outRect
中返回它。要等间距和等大小,如果你计算正确,你会发现这些偏移值不是常数,它们会根据它们的列索引和行索引而改变。让我们推导偏移值的公式。带外边缘
在第一种情况下,我们考虑边缘周围的边距。
无外缘
在这里,我们在不考虑边的情况下计算。
让我们编写代码...
6gpjuf905#
您可以在回收器视图中使用addItemDecoration方法。
项装饰类文件:-
在回收视图中实现: