我有自定义ViewPager
和PagerAdapter
,它们正在instantiateItem
内加载项目。如果我第一次使用设置的项目列表对其进行初始化,则效果很好。
但是,当我在列表上调用refresh并且要用新的(完全不同的)列表填充适配器时,在调用viewPager.adapter?.notifyDataSetChanged()
之后,PagerAdapter停止正常工作,并且这些项目是没有内容的空白页面,我可以在其中滑动在用户界面中。
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内部具有函数,该函数根据列表中的最高子级设置其高度。如果列表是静态的,它可以工作,但是当我刷新它时,它现在不工作。
答案 0 :(得分:0)
重新创建整个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
进行调整。