RecyclerView 中使用 StaggeredGridLayout 的全宽页脚或最后一项

Posted

技术标签:

【中文标题】RecyclerView 中使用 StaggeredGridLayout 的全宽页脚或最后一项【英文标题】:Full width footer or last item in RecyclerView using StaggeredGridLayout 【发布时间】:2020-12-30 04:29:55 【问题描述】:

所以这很棘手。我发现最接近这个工作的是这个answer的修改版本。我使最后一个项目与我想要全宽且不可见的视图具有相同的高度。然后我添加一个 itemdecoration 并将其绘制在列表中的最后一项应该可见的位置,如下所示:

class StickyDecoration (private val stickyView: View) : ItemDecoration() 

    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) 
        super.onDraw(c, parent, state)

        // layout basically just gets drawn on the reserved space on top of the first view
        stickyView.layout(parent.left, 0, parent.right, stickyView.measuredHeight)
        for (i in 0 until parent.childCount) 
            val view: View = parent.getChildAt(i)
            if (parent.getChildAdapterPosition(view) == parent.childCount - 1) 
                c.save()

                val rectf = Rect()
                view.getGlobalVisibleRect(rectf)
                c.translate(0f, (rectf.top).toFloat())

                stickyView.draw(c)
                c.restore()
                break
            
        
    

    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) 
        outRect.setEmpty()
    

这种方法的问题是,当 recyclerview 中最后一个上方的项目从视图中消失时,rectf.topview.top 的值或我能想到的任何测量值都会发生飞跃并取代最后一个项目。

有谁知道使用 StaggeredGridLayoutManager 将全宽最后一项或页脚添加到 recyclerview 的方法?我知道它适用于 Gridlayout,但在我的情况下它不是一个选项。

或者,如果您知道一个值,它可以在屏幕上最后一个项目的正确位置而没有任何值跳转?

编辑:

我想要实现的更多细节。

它应该是一个 StaggeredGridLayout,在最后一项下方有一个页脚,它是全宽的,并且随着其余内容滚动。

【问题讨论】:

这里有点难以理解你想要完成的事情。正在发生的事情以及您所期望的图片/GIF 会说明这一点 @SiddharthSharma 添加了更多详细信息 【参考方案1】:

在适配器中,您可以像这样为页脚 UI 添加条件:

@Override
    public int getItemViewType(int position) 
        if (// normal UI) 
            return VIEW_TYPE_NORMAL;
         else 
            return VIEW_TYPE_FOOTER;
        
    

onBindViewHolder 中,您可以像这样为 VIEW_TYPE_FOOTER 添加。

StaggeredGridLayoutManager.LayoutParams layoutParams =
                        (StaggeredGridLayoutManager.LayoutParams) ((YourViewHolder) holderType).itemView.getLayoutParams();
                /*
                 * to make View to occupy full width of the parent
                 */
                layoutParams.setFullSpan(true);

【讨论】:

【参考方案2】:

onBindViewHolder 中使用 isFullSpan

override fun onBindViewHolder(holder: LoadStateViewHolder, loadState: LoadState) 
        holder.bind(loadState)
        val layoutParams = holder.itemView.layoutParams as StaggeredGridLayoutManager.LayoutParams
        layoutParams.isFullSpan = true
    

【讨论】:

【参考方案3】:

要使用 StaggeredGridLayoutManager 在 recyclerView 中制作全宽页脚,您可以执行以下操作。创建自定义 ItemDecoration:

class FooterDecoration (private val footerView: View) : ItemDecoration() 

    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) 
        super.onDraw(c, parent, state)

        footerView.layout(parent.left, 0, parent.right, footerView.measuredHeight)
        val count = parent.adapter!!.itemCount

        val view: View = parent.getChildAt(parent.childCount - 1)
        if (parent.getChildAdapterPosition(view) == count - 1) 
            c.save()

            val rect = Rect()
            view.getGlobalVisibleRect(rect)
            c.translate(0f, (rect.top).toFloat())

            footerView.draw(c)
            c.restore()
        
    

然后在你的 recyclerView 中膨胀你想要使用的视图并将其添加为项目装饰:

recyclerView.apply 
    val footerView: View = LayoutInflater.from(context).inflate(R.layout.item_footer_placeholder, this, false)
    val measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
    footerView.measure(measureSpec, measureSpec)
    addItemDecoration(ServicesFooterDecoration(footerView))


【讨论】:

以上是关于RecyclerView 中使用 StaggeredGridLayout 的全宽页脚或最后一项的主要内容,如果未能解决你的问题,请参考以下文章

RecyclerView | 在 RecyclerView 中使用 header 快人一步

Eclipse中使用recyclerview时出现Caused by: java.lang.NoClassDefFoundError: android.support.v7.recyclerview.

Android 开发中使用 Recyclerview

如何在 RecyclerView 中使用 ItemAnimator?

如何彻底更改 recyclerview 中的 item 布局中的某个控件的某个属性

在选项卡式活动中使用 RecyclerView 的 OnScreenRotation