获取GridLayoutManager中视图所在的列数

6
我有不同类型的项目在使用GridLayoutManager以动态列数的方式呈现在RecyclerView中。问题是,我有一个RecyclerView.ItemDecoration仅适用于某些类型A的项目。该RecyclerView.ItemDecoration对于左侧列上的这些项目添加了左/开始边缘的间距,并对右侧列上的这些项目添加了右/结束边缘的间距。它基本上是为了使项目看起来更加居中和伸展(这在平板电脑/横向模式上使用)。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 和项目的真实位置,即忽略非 type A 项目时它在适配器中所在的位置。这有一些其他的问题,我不会详细说明,但这不是正确的解决方法。
我尝试的另一件事是检查视图(更靠左还是更靠右)上要应用项装饰的位置。但问题在于当运行此装饰器时,视图尚未呈现。在视图上添加 ViewTreeObserver.OnGlobalLayoutListener 是无效的,因为在视图呈现时,项目装饰已经应用,对视图没有任何影响。
我想做的是检查项目是否在“列0”或“列1”中,并相应地添加边距。
我不知道如何做到这一点,并且在查看可通过 parent.layoutManager as GridLayoutManager 访问的 GridLayoutManager 所提供的内容时也没有找到方法。
有什么想法吗?谢谢。
1个回答

17

因为这篇内容太长了,所以我把它作为答案分享。请让我知道结果,如果不起作用,我会删除它。

另外,很抱歉我只懂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

这正是我想做的!没想到可以从 LayoutParams 中获取跨度。运行得很好,谢谢! - Javier Mendonça
这个答案节省了我的时间。点赞。非常感谢! - Dima Kozhevin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接