如何在RecyclerView ItemDecorator中获取偏移量

时间:2015-11-23 22:28:58

标签: android android-recyclerview

我为ItemDecorator写了两个RecyclerView。每个都在getItemOffsets()中添加一些顶部偏移量。让我们说:

  • 第一个装饰者添加20dp顶部偏移
  • 第二个分配器添加30dp顶部偏移量

现在,当我将它们都添加到RecyclerView时,每个项目都正确地偏移了50dp,这很好。

但是问题出现了: 如何在onDraw / onDrawOver

中获得此偏移量

通常,装饰者通过遍历parent.getChildAt(i)内容并获取child.getTop()来绘制他们的内容,例如绘制上面RecyclerView的子视图。

但在这种情况下,这样做会混淆其他装饰器的绘制,因为它也会使用child.getTop()

所以目前两个装饰师似乎都需要了解彼此和彼此的身高。

我在这里遗漏了什么吗?我希望我是。

编辑: 我向Android问题跟踪器报告了一个问题,似乎这将会有效。明确它以跟踪进度: https://code.google.com/p/android/issues/detail?id=195746

1 个答案:

答案 0 :(得分:14)

tl; dr 不,你没有遗漏任何东西。但你可以获得getItemOffsets所需的值,虽然它对我来说似乎有点脏。

基本上只有一个选项来获取装饰高度而不是自己管理装饰:LayoutManager.getDecoratedTop();

<强>的onDraw

onDraw中,您获得了recyclerView的整个画布,c.getClipBounds()不包含任何信息。虽然添加装饰的javadoc说装饰应该只用他们的界限绘制。

另外,获取parent.getLayoutManager().getDecoratedTop()会在每个装饰中给出相同的值,因为这里已经太晚了,这些值是用于布局目的。

我们太晚了,布局已经完成,我们错过了它。

<强> getItemOffsets

  

请注意,我使用LinearLayoutManager对以下内容进行了测试,但它可能与其他人无法合作(绝大多数都不适用于大多数自定义内容)。由于我依赖于测量这些未记录的调用之间发生的事情,因此给定的解决方案可能会破坏未来的版本。

我觉得我需要免责声明。我找到了一个有效的解决方案(观看mOffset):

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
    mOffset = parent.getLayoutManager().getTopDecorationHeight(view);
    outRect.set(0, 10, 0, 0);
}

这很有效,因为在计算孩子的总插入时,recyclerview是updating the views package local LayoutParams variable。虽然我们无法访问布局参数变量本身,但调用getTopDecorationHeight实际上使用了(当前)脏插图,为我们提供了正确的值。
因此,您可以在应用之前获得先前装饰的偏移量!

要应用它,只需在绘制装饰时移除其他装饰偏移:

c.drawRect(child.getLeft() + child.getTranslationX(),
        mOffset + layoutManager.getDecoratedTop(child) + child.getTranslationY(),
        child.getRight() + child.getTranslationX(),
        child.getBottom() + child.getTranslationY(), paint);

这实际上会应用其他装饰偏移,然后从正确的顶部绘制自己的装饰。

有些问题

现在,这是默认用例的基本工作解决方案。的 BUT 即可。如果根据项目VIEW_TYPE或适配器位置有不同的偏移量,那么事情会变得棘手。

您将复制逻辑并为各种视图类型保留各种偏移量,或者您必须为每个视图或视图类型存储/检索偏移量。

为此,您可以使用view.setTag(key, object)添加一些自定义标记,或者使用传递的RecyclerView.State对象执行类似操作。