使用 StaggeredGridLayout 的 RecyclerView 中的全宽页脚或最后一项
Full width footer or last item in RecyclerView using StaggeredGridLayout
所以这很棘手。我发现最接近这个工作的东西是这个 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.top
或 view.top
的值或我能想到的任何测量值都会发生飞跃,取代最后一项。
有谁知道使用 StaggeredGridLayoutManager 将全宽最后一项或页脚添加到 recyclerview 的方法吗?我知道它适用于 Gridlayout,但在我的情况下它不是一个选项。
或者,如果您知道一个值可以到达屏幕上最后一个项目的正确位置,而不会出现值的任何跳跃?
编辑:
关于我想要实现的目标的更多详细信息。
它应该是一个在最后一项下面有一个页脚的 StaggeredGridLayout,它是全宽的并且与其余内容一起滚动。
要使用 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))
}
在适配器中,您可以像这样为页脚 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);
在 onBindViewHolder 中使用 isFullSpan .
override fun onBindViewHolder(holder: LoadStateViewHolder, loadState: LoadState) {
holder.bind(loadState)
val layoutParams = holder.itemView.layoutParams as StaggeredGridLayoutManager.LayoutParams
layoutParams.isFullSpan = true
}
所以这很棘手。我发现最接近这个工作的东西是这个 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.top
或 view.top
的值或我能想到的任何测量值都会发生飞跃,取代最后一项。
有谁知道使用 StaggeredGridLayoutManager 将全宽最后一项或页脚添加到 recyclerview 的方法吗?我知道它适用于 Gridlayout,但在我的情况下它不是一个选项。
或者,如果您知道一个值可以到达屏幕上最后一个项目的正确位置,而不会出现值的任何跳跃?
编辑:
关于我想要实现的目标的更多详细信息。
它应该是一个在最后一项下面有一个页脚的 StaggeredGridLayout,它是全宽的并且与其余内容一起滚动。
要使用 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))
}
在适配器中,您可以像这样为页脚 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);
在 onBindViewHolder 中使用 isFullSpan .
override fun onBindViewHolder(holder: LoadStateViewHolder, loadState: LoadState) {
holder.bind(loadState)
val layoutParams = holder.itemView.layoutParams as StaggeredGridLayoutManager.LayoutParams
layoutParams.isFullSpan = true
}