如何在RecyclerView ItemDecorator中获取偏移量 [英] How to get an offset in RecyclerView ItemDecorator

查看:471
本文介绍了如何在RecyclerView ItemDecorator中获取偏移量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为RecyclerView写了两个ItemDecorator.每个都在getItemOffsets()中添加一些顶部偏移.假设:

I have written two ItemDecorator's for RecyclerView. Each adds some top offset in getItemOffsets(). Let's say:

  • 第一个装饰器添加了20dp的顶部偏移量
  • 第二个分度器增加了30dp的顶部偏移量

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

Now, when I add both of them to RecyclerView, each item is correctly offsetted by 50dp, that's good.

但是问题来了: 如何在onDraw/onDrawOver中获得此偏移量?

But here comes the question: How do I get this offset in onDraw/onDrawOver?

通常,装饰器通过遍历parent.getChildAt(i)内容并获取child.getTop()来绘制其内容,例如在RecyclerView的子视图上方进行绘制.

Usually decorators draw their stuff by traversing parent.getChildAt(i) stuff and getting child.getTop() for example to draw above child view of RecyclerView.

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

But in this case, doing so would mix up the drawing of other decorator, because it would also use child.getTop().

所以目前看来,两个装饰者都需要了解彼此以及彼此的高度.

So at the moment it seems like both decorators need to know about each other and each other's height.

我在这里错过了什么吗?我希望我是.

Am I missing something here? I hope I am.

编辑:我向Android问题跟踪器报告了一个问题,看来可以解决此问题.给它加注星标以跟踪进度: https://code .google.com/p/android/issues/detail?id = 195746

推荐答案

tl; dr 不,您不会丢失任何东西.但是您可以在getItemOffsets中获得所需的值,尽管对我来说似乎有点脏.

tl;dr No you are not missing anything. But you can get the values needed in getItemOffsets, albeit it seems a little bit dirty to me.

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

Basically there is only one option of getting the decorated height other than managing decorations yourself: LayoutManager.getDecoratedTop();

onDraw

onDraw中,您将获得recyclerView的整个画布,c.getClipBounds()不包含任何信息.尽管添加装饰的javadoc指出装饰应该仅以边界绘制.

In onDraw you get the whole canvas of the recyclerView, c.getClipBounds() does not hold any information. Albeit the javadoc of adding decorations says that decorations should just draw withing their bounds.

此外,获取parent.getLayoutManager().getDecoratedTop()会在每个装饰中为您提供相同的值,因为在这里已经为时已晚,这些值仅用于布局.

Also, getting parent.getLayoutManager().getDecoratedTop() will give you the same values in every decoration, since it's already too late here, those values are for layouting purposes.

我们为时已晚,布局已经完成,我们错过了.

We are too late, layouting is done and we missed it.

getItemOffsets

请注意,我用LinearLayoutManager测试了以下内容,它可能也不能与其他内容一起使用(大多数绝对不能与大多数自定义项一起使用).由于我依靠的是衡量这些调用之间发生的事件(未记录),因此给定的解决方案可能会在将来的某些版本中失效.

Please note that I tested the following with a LinearLayoutManager and it might as well not work with the others (Most definitely not with most custom ones). Since I am relying on measuring happening between those calls, which is not documented, the given solution might break with some future version.

我只是觉得我需要这个免责声明.我找到了一个可行的解决方案(观看mOffset):

I just felt I needed that disclaimer. I found a working solution (watch the 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在计算孩子的总身高时为

This works, because the recyclerview, when calculating the total inset of the child, is updating the views package local LayoutParams variable. While we cannot access the layout parameter variable itself, calling getTopDecorationHeight actually uses the (currently) dirty inset, giving us the proper value.
Hence, you can get the offset of the previous decorations before applying your own!

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

To apply it, just remove the other decorations offset when drawing your decoration:

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

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

This will actually apply the other decorations offset, then draw your own from the correct top.

一些问题

这是默认用例的基本工作解决方案. 但是.如果根据项目VIEW_TYPE或适配器的位置使用不同的偏移量,则会遇到麻烦.

This is now a basic, working solution for the default usecase. BUT. If you have different offsets depending on the item VIEW_TYPE or the adapter position things get tricky.

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

You will either duplicate your logic and keep various offsets for various view types or you have to store / retrieve the offset for every view or viewtype.

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

To do so, you could either add some custom tag with view.setTag(key, object) or doing something similar with the RecyclerView.State object that's getting passed around.

这篇关于如何在RecyclerView ItemDecorator中获取偏移量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆