我有自定义的ViewPager
和PagerAdapter
,它们正在instantiateItem
中加载项目。如果我第一次使用设置的项目列表对其进行初始化,它将很好用。
但是当我在列表上调用refresh,并且我想用新的(完全不同的)列表填充适配器时,在调用viewPager.adapter?.notifyDataSetChanged()
之后,PagerAdapter停止正常工作,并且这些项目是没有内容的空白页面,我可以在UI中对其进行滑动。
PageScreen
不是Fragment
。只是ViewGroup
容器正在夸大布局并从特定项目设置值。它类似于ViewHolder
中的Binder
+ RecyclerView
。
也instatiateItem()
仅被调用一次,因为我添加了新列表并调用notifyDataSetChanged()
。首先,它被称为3个项目,即第一个列表中的PageScreen
个项目。
//init
val pages = mutableListOf<PageScreen>()
pages.add(PageScreen(activity, app, itemJs1, onClick = {onItemClicked(itemJs1.id)}))
pages.add(PageScreen(activity, app, itemJs2, onClick = {onItemClicked(itemJs2.id)}))
pages.add(PageScreen(activity, app, itemJs3, onClick = {onItemClicked(itemJs3.id)}))
swipePager.adapter = CustomPagerAdapter(pages).also { it.notifyDataSetChanged() }
...
//on refresh after API call
pages.clear()
contentList.forEach{item-> pages.add(PageScreen(activity, app, item, onClick = {onItemClicked(item.id)}))}
(swipePager.adapter as? CustomPagerAdapter)?.notifyDataSetChanged()
也尝试过此操作(结果相同):
//on refresh after API call
val newPages = mutableListOf<PageScreen>()
contentList.forEach{item-> newPages.add(PageScreen(activity, app, item, onClick = {onItemClicked(item.id)}))}
swipePager.adapter = CustomPagerAdapter(newPages).also { it.notifyDataSetChanged() }
适配器:
class CustomPagerAdapter(private var pageList: MutableList<PageScreen>) : PagerAdapter() {
override fun isViewFromObject(view: View, `object`: Any): Boolean {
return view == `object`
}
override fun getCount(): Int {
return pageList.size
}
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
container.removeView(`object` as View)
}
override fun instantiateItem(container: ViewGroup, position: Int): View {
val layout = pageList[position].getScreen(container)
container.addView(layout)
return layout
}
}
此外,我试图通过从ViewPager contentView中删除项目并为每个项目调用notifyDataSetChanged()
来正确刷新项目(我希望这是在我调用instantiateItem()
时由PagerAdapter和ViewPager在内部完成的。但结果与上面相同。现在每个页面都是空白。以下功能已添加到CustomPagerAdapter
。
fun refreshItems(vp: ViewPager, data: MutableList<PageScreen>){
pageList.apply {
forEachIndexed{pos, item->
item.screenView?.let { sv->
destroyItem(vp, pos, sv)
}
}
clear()
addAll(data)
forEachIndexed { pos, _ -> instantiateItem(vp, pos) }
}
notifyDataSetChanged()
}
更新:我设法通过将ViewPager高度设置为固定值而不是WRAP_CONTENT
来“解决”此问题,但这不是解决方案。我希望ViewPager具有动态高度,因为它的某些子级可以具有不同的高度+将某些内容设置为静态不是Android中的好方法。某些带有方形显示屏的手机可能会裁剪页面。
发生了什么事,当我替换了所有项目时,由于某些未知原因,那些“空白”页面是高度为0px和宽度为0px的项目。
如果我将ViewPager的高度替换为dp值,它将“起作用”。但是当我替换这些视图时,第一项始终是空白。但是当我滚动到第三个并回到第一个时,由于某种原因该项目在那里。
而且我也没有那个身高问题。我在ViewPager内部具有函数,该函数根据列表中的最高子级设置其高度。如果列表是静态的,它可以工作,但是当我刷新它时,它现在不工作。
重新创建整个ViewPagerAdapter
是解决此问题的方法。
我在onPageSelected()
内部调用了API,并记住了返回给监听器函数的位置。
然后我重新创建了整个适配器,如下所示:
swipePager.apply {
adapter = null
adapter = CustomPagerAdapter(newPages)
adapter?.notifyDataSetChanged()
invalidate()
}
刷新后,我滚动到这样的记忆位置:
setCurrentItem(position, true)
此解决方案不会留下空白页,但我必须为ViewPager
设置静态高度,这在mdpi
屏幕上可能是一个问题,有时无法从dp
布局中正确重绘特定的XML
值。出现此问题的电话例如是Sony Xperia E5
,它具有xhdpi
屏幕,而我的ViewPager
的一部分是从底部裁剪的。
对于dimens.xml
和mdpi
,必须分别使用xhdpi
进行手动调整。