解决paging3配合GridLayoutManager时footer不能占一行的问题

2021-12-10 10:54:01 浏览数 (2)

使用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能够独占一行了。

0 人点赞