使用paging3开发时,官方demo只有包含LinearLayout的部分代码, 当我们需要配合GridLayoutManager(spanCount=2)时, 发现footer不能适配占满一行,而是单独占了一个spanSize。
n0QoE.png
我们知道,GridLayoutManager可以通过设置spanSizeLookup来达到某些Item填充多个spanSize的目的 如下:
代码语言:javascript复制 spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return if(position == itemCount-1) spanCount else 1
}
}
但是使用paging3和ConcatAdapter配合时,footer并不会一直在最下方展示, 因为LoadStateAdapter 会根据paging的加载状态动态添加及删除footerAdapter, 所以position的最后一行不一定是footer, 源码如下:
代码语言:javascript复制abstract class LoadStateAdapter<VH : RecyclerView.ViewHolder> : RecyclerView.Adapter<VH>() {
var loadState: LoadState = LoadState.NotLoading(endOfPaginationReached = false)
set(loadState) {
if (field != loadState) {
val oldItem = displayLoadStateAsItem(field)
val newItem = displayLoadStateAsItem(loadState)
if (oldItem && !newItem) {
notifyItemRemoved(0)
} else if (newItem && !oldItem) {
notifyItemInserted(0)
} else if (oldItem && newItem) {
notifyItemChanged(0)
}
field = loadState
}
}
}
此时我们只能通过ConcatAdapter查询itemViewType来处理spanSizeLookup , 需要先创建footer
代码语言:javascript复制 //创建footer和empty
val footer = FooterAdapter(adapter)
...
...
//ConcatAdapter.Config.Builder().setIsolateViewTypes(false).build() 是重点,否则拿不到需要的itemviewtype
val concatAdapter = ConcatAdapter(ConcatAdapter.Config.Builder().setIsolateViewTypes(false).build(),adapter, footer)
代码语言:javascript复制//记得重写LoadStateAdapter中的getItemType方法
override fun getStateViewType(loadState: LoadState): Int {
return VIEW_TYPE
}
通过如上代码可以创建ConcatAdapter, 然后重写spanSizeLookup
代码语言:javascript复制 GridLayoutManager(
requireContext(),
2,
GridLayoutManager.VERTICAL,
false
).apply {
spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return if (concatAdapter
?.getItemViewType(position) in arrayOf(
BaseEmptyAdapter.VIEW_TYPE,
BasePlaceholderAdapter.VIEW_TYPE,
FooterAdapter.VIEW_TYPE
)
) spanCount else 1
}
}
}
通过以上设置,即可完成paging3与GridLayoutManager的联动,并且保证footer能够独占一行了。