There are several occasions when we need to implement sticky header for some list of data displayed in RecyclerView. And of course, Android doesn't have a native UI component to implement this easily. There are several third-party libraries which we can use to achieve this functionality. But using third party libraries always comes at a cost. There is always a doubt of whether the library we are using will be updated for future versions or not, apart from the additional overhead of LOC and app size that these libraries add. One simpler way of achieving this same behavior without having to use any third party library is to write a custom RecyclerView ItemDecoration and override onDrawOver(canvas: Canvas, parent: RecyclerView, state: State) function. Below is the description on how to do that. Please feel free to customize this implementation to meet your requirements:
在很多情况下,我们需要为RecyclerView显示的某些数据列表实现粘性标头。 当然,Android没有本机UI组件可以轻松实现此功能。 我们可以使用几个第三方库来实现此功能。 但是使用第三方库总是要付出代价的。 除了这些库添加的LOC额外开销和应用程序大小外,我们一直在怀疑我们正在使用的库是否会针对将来的版本进行更新。 无需使用任何第三方库即可实现相同行为的一种简单方法是编写自定义RecyclerView ItemDecoration并重写onDrawOver(canvas: Canvas, parent: RecyclerView, state: State)函数。 以下是有关如何执行此操作的说明。 请随时自定义此实现,以满足您的要求:
This is a wrapper around ItemDecoration abstract class. As it is stated on the documentation, these ItemDecorations are drawn in the order they were added, before the views and after the items.
这是ItemDecoration抽象类的包装。 如文档中所述,这些ItemDecorations是按照添加顺序,在视图之前和之后绘制的。
In this implementation of the custom decoration, we are going to provide three things as parameter:
在自定义装饰的此实现中,我们将提供三件事作为参数:
RecyclerView adapter RecyclerView适配器 Root view, e.g. the fragment’s root where the RecyclerView exists 根视图,例如RecyclerView所在的片段的根 Layout resource id for the header to be used 标题使用的布局资源IDAbove is the basic structure for the custom ItemDecoration. Now we have to understand what customization goes inside the onDrawOver function.
上面是自定义ItemDecoration的基本结构。 现在,我们必须了解onDrawOver函数中包含哪些自定义onDrawOver 。
Let’s continue customizing onDrawOver() function:
让我们继续自定义 onDrawOver() 函数:
layoutHeaderView(topChild: View)
layoutHeaderView(topChild:View)
Canvas.drawHeaderView(topView: View, secondChild: View?)
Canvas.drawHeaderView(topView:View,secondChild:View?)
calculateHeaderTop(topView: View, secondChild: View?): Float
computeHeaderTop(topView:View,secondChild:View?):浮动
In onDrawOver()function,
在onDrawOver()函数中,
we get the reference for the first and second item of the RecyclerView
我们获得RecyclerView的first项和second项的参考
we retrieve the header text for the top child
我们检索顶级子的header文本
measure the header 测量标题 calculate header top and draw the header 计算标题顶部并绘制标题fun getHeaderForCurrentPosition(topPosition) : Int{} returns the header text for the given position.
fun getHeaderForCurrentPosition(topPosition) : Int{} 返回给定位置的header文本。
fun layoutHeaderView(topView: View){} measures the EXACT width of the header view to be drawn. Note that the height is unspecified as we are using the header view's measuredHeight.
fun layoutHeaderView(topView: View){} 测量要绘制的标题视图的EXACT宽度。 注意, height是unspecified因为我们使用的是标题视图的measuredHeight 。
fun calculateHeaderTop(topView: View, secondView: View?):Float{} calculates the top of the header. If second view is visible, we take reference of secondView's top, else the header's top is topView's top.
fun calculateHeaderTop(topView: View, secondView: View?):Float{} 计算标题的top 。 如果第二个视图可见,则引用secondView的顶部,否则标题的顶部为topView的顶部。
The custom ItemDecoration can be assigned to the recyclerView in the Fragment class.
可以将自定义ItemDecoration分配给Fragment类中的recyclerView 。
When we initialize the list with the items, the header text for the first item will be displayed as soon as all data is inflated. Then as we scroll through the list, when the top of the second item (plus some threshold is optional) touches the bottom of the sticky header then the header for the second item is drawn. And this continues as we scroll up through the list. As we scroll down through the list, the reverse behavior occurs and the header text are drawn. The adapter class is responsible for providing the header text for any given position if the position is within bounds of the items size.
当我们使用这些项目初始化列表时,所有数据被填充后,将立即显示第一个项目的标题文本。 然后,当我们滚动浏览列表时,当second项目的top (加上一些阈值是可选的)碰到sticky header的bottom ,便绘制了第二个项目的header 。 当我们向上滚动列表时,这种情况仍在继续。 当我们向下滚动列表时,会发生相反的行为并绘制标题文本。 如果位置在项目大小的范围内,则适配器类负责为任何给定位置提供标题文本。
This is my first article in medium and I would highly appreciate feedback :)Also, please check this article about Single Choice Recycler View Adapter. Thank you!
这是我的第一篇中型文章,非常感谢您提供反馈意见:)此外,请查看有关Single Choice Recycler View Adapter的本文 。 谢谢!
Sample implementation can be found here for demonstration purposes:- https://github.com/bigyanthapa/Sample-Sticky-Header
可以在此处找到示例实现以进行演示: -https : //github.com/bigyanthapa/Sample-Sticky-Header
翻译自: https://medium.com/swlh/android-recyclerview-stickyheader-without-external-library-25845ec3e20f