使用paging3開發(fā)時,官方demo只有包含LinearLayout的部分代碼,
當(dāng)我們需要配合GridLayoutManager(spanCount=2)時,
發(fā)現(xiàn)footer不能適配占滿一行,而是單獨占了一個spanSize。

n0QoE.png
我們知道,GridLayoutManager可以通過設(shè)置spanSizeLookup來達(dá)到某些Item填充多個spanSize的目的
如下:
spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return if(position == itemCount-1) spanCount else 1
}
}
但是使用paging3和ConcatAdapter配合時,footer并不會一直在最下方展示,
因為LoadStateAdapter 會根據(jù)paging的加載狀態(tài)動態(tài)添加及刪除footerAdapter,
所以position的最后一行不一定是footer,
源碼如下:
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 ,
需要先創(chuàng)建footer
//創(chuàng)建footer和empty
val footer = FooterAdapter(adapter)
...
...
//ConcatAdapter.Config.Builder().setIsolateViewTypes(false).build() 是重點,否則拿不到需要的itemviewtype
val concatAdapter = ConcatAdapter(ConcatAdapter.Config.Builder().setIsolateViewTypes(false).build(),adapter, footer)
//記得重寫LoadStateAdapter中的getItemType方法
override fun getStateViewType(loadState: LoadState): Int {
return VIEW_TYPE
}
通過如上代碼可以創(chuàng)建ConcatAdapter,
然后重寫spanSizeLookup
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
}
}
}
通過以上設(shè)置,即可完成paging3與GridLayoutManager的聯(lián)動,并且保證footer能夠獨占一行了。