如何在RecyclerView ItemDecorator中获取偏移量

dim*_*suz 12 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

Dav*_*jak 15

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

基本上除了自己管理装饰之外,只有一个选项可以获得装饰高度:LayoutManager.getDecoratedTop();

的onDraw

onDraw你获得recyclerView的整个画布,c.getClipBounds()没有任何信息.虽然添加装饰的javadoc说装饰应该只是绘制它们的界限.

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

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

getItemOffsets

请注意,我用a测试了以下内容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);
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为在计算子项的总插入时,recyclerview正在更新视图包本地LayoutParams变量.虽然我们无法访问布局参数变量本身,但调用getTopDecorationHeight实际上使用了(当前)脏插图,为我们提供了正确的值.
因此,您可以在应用自己之前获得先前装饰的偏移量!

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

c.drawRect(child.getLeft() + child.getTranslationX(),
        mOffset + layoutManager.getDecoratedTop(child) + child.getTranslationY(),
        child.getRight() + child.getTranslationX(),
        child.getBottom() + child.getTranslationY(), paint);
Run Code Online (Sandbox Code Playgroud)

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

一些问题

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

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

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