获取视图在 GridLayoutManager 上的列号
Get the column number where a view is on a GridLayoutManager
我使用带有动态列号的 GridLayoutManager
在 RecyclerView
中呈现不同类型的项目。问题是,我有一个 RecyclerView.ItemDecoration
可以申请 Type A
项目。此 RecyclerView.ItemDecoration
将 left/start 的边距添加到左侧列中的那些项目,并将 right/end 的边距添加到右侧列中的那些项目。这基本上是为了让项目看起来更居中一点,所以拉伸(这用于 tablet/landscape 模式)。 RecyclerView
网格看起来像这样:
| A | | A |
| A | | A |
| B |
| A | | A |
| A | | A |
| B |
| A | | A |
ItemDecoration
看起来像这样:
class TabletGridSpaceItemDecoration(private val space: Int) : RecyclerView.ItemDecoration() {
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) = with(outRect) {
val isTypeAItemLayout = view.findViewById<ConstraintLayout>(R.id.type_a_item_container) != null
if (isTypeAItemLayout) {
val adapterPosition = parent.getChildAdapterPosition(view)
if (adapterPosition % 2 == 0) {
left = space
right = 0
} else {
left = 0
right = space
}
}
}
}
这个装饰器的问题是,在列表中的第一个 type B
项之后,下一个 type A
项的索引被搞砸了。所以根据提供的示例 B
之后的第一项将有 adapterPosition == 5
,因此根据 TabletGridSpaceItemDecoration
应该在右边添加边距,这是不正确的。
我试着用 HashMap
来保持 adapterPosition
和项目的真实位置,即忽略非 [=20= 它在适配器上的位置] 项目。这还有一些其他问题我不会详细介绍,但感觉不是正确的方法。
我尝试的另一件事是检查将应用项目装饰的视图在屏幕上的位置(更靠左或更靠右)。这样做的问题是当这个装饰器是 运行 时视图还没有被渲染。在视图上添加 ViewTreeObserver.OnGlobalLayoutListener
是没有价值的,因为在呈现视图时项目装饰已经应用,这对视图没有影响。
我想做的是检查一个项目是否在 "column 0" 或 "column 1" 中并相应地添加边距。
我不知道这怎么可能,也没有找到方法查看 GridLayoutManager
提供的内容,可以通过 parent.layoutManager as GridLayoutManager
.[=30= 访问]
有什么想法吗?谢谢
我将此作为答案分享,因为评论太长了。让我知道结果,如果不起作用,我会删除。
此外,很抱歉在 Java 中分享。我对 Kotlin 是文盲
您可以尝试使用 spanIndex
而不是使用位置
@Override
public void getItemOffsets(final Rect outRect, final View view, final RecyclerView parent, final State state) {
...
if(isTypeAItemLayout) {
int column = ((GridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex();
if (column == 0) {
// First Column
} else {
// Second Column
}
}
}
更新
对于 Kotlin:
val column: Int = (view.layoutParams as GridLayoutManager.LayoutParams).spanIndex
我使用带有动态列号的 GridLayoutManager
在 RecyclerView
中呈现不同类型的项目。问题是,我有一个 RecyclerView.ItemDecoration
可以申请 Type A
项目。此 RecyclerView.ItemDecoration
将 left/start 的边距添加到左侧列中的那些项目,并将 right/end 的边距添加到右侧列中的那些项目。这基本上是为了让项目看起来更居中一点,所以拉伸(这用于 tablet/landscape 模式)。 RecyclerView
网格看起来像这样:
| A | | A |
| A | | A |
| B |
| A | | A |
| A | | A |
| B |
| A | | A |
ItemDecoration
看起来像这样:
class TabletGridSpaceItemDecoration(private val space: Int) : RecyclerView.ItemDecoration() {
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) = with(outRect) {
val isTypeAItemLayout = view.findViewById<ConstraintLayout>(R.id.type_a_item_container) != null
if (isTypeAItemLayout) {
val adapterPosition = parent.getChildAdapterPosition(view)
if (adapterPosition % 2 == 0) {
left = space
right = 0
} else {
left = 0
right = space
}
}
}
}
这个装饰器的问题是,在列表中的第一个 type B
项之后,下一个 type A
项的索引被搞砸了。所以根据提供的示例 B
之后的第一项将有 adapterPosition == 5
,因此根据 TabletGridSpaceItemDecoration
应该在右边添加边距,这是不正确的。
我试着用
HashMap
来保持adapterPosition
和项目的真实位置,即忽略非 [=20= 它在适配器上的位置] 项目。这还有一些其他问题我不会详细介绍,但感觉不是正确的方法。我尝试的另一件事是检查将应用项目装饰的视图在屏幕上的位置(更靠左或更靠右)。这样做的问题是当这个装饰器是 运行 时视图还没有被渲染。在视图上添加
ViewTreeObserver.OnGlobalLayoutListener
是没有价值的,因为在呈现视图时项目装饰已经应用,这对视图没有影响。
我想做的是检查一个项目是否在 "column 0" 或 "column 1" 中并相应地添加边距。
我不知道这怎么可能,也没有找到方法查看 GridLayoutManager
提供的内容,可以通过 parent.layoutManager as GridLayoutManager
.[=30= 访问]
有什么想法吗?谢谢
我将此作为答案分享,因为评论太长了。让我知道结果,如果不起作用,我会删除。
此外,很抱歉在 Java 中分享。我对 Kotlin 是文盲
您可以尝试使用 spanIndex
@Override
public void getItemOffsets(final Rect outRect, final View view, final RecyclerView parent, final State state) {
...
if(isTypeAItemLayout) {
int column = ((GridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex();
if (column == 0) {
// First Column
} else {
// Second Column
}
}
}
更新
对于 Kotlin:
val column: Int = (view.layoutParams as GridLayoutManager.LayoutParams).spanIndex