ViewPager 列表刷新无法正常工作
ViewPager list refresh is not working properly
我有自定义 ViewPager
和 PagerAdapter
,它们正在 instantiateItem
中加载项目。如果我第一次使用设置的项目列表初始化它,它工作正常。
但是当我在列表上调用刷新并且我想用新的(完全不同的)列表填充适配器时,在调用 viewPager.adapter?.notifyDataSetChanged()
之后,PagerAdapter 停止正常工作并且那些项目是没有内容的空白页面,我可以在 UI.
中滑动它们
PageScreen
不是 Fragment
。它只是 ViewGroup
容器,它正在膨胀布局并设置特定项目的值。类似于RecyclerView
中的ViewHolder
+ Binder
.
另外 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 中移除并为每个项目调用 instantiateItem()
来正确刷新项目(我希望这是在我调用 notifyDataSetChanged()
时由 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()
}
更新:
我设法 "fix" 通过将 ViewPager 高度设置为固定值而不是 WRAP_CONTENT
但这不是解决方案。我想要具有动态高度的 ViewPager,因为它的一些 children 可以有不同的高度 + 在 Android 中将某些东西设置为静态不是好的方法。一些带有方形显示屏的手机可能会裁剪页面。
发生的事情是当我替换所有项目时,那些 "blank" 页面是高度为 0px 和宽度为 0px 的项目,原因不明。
如果我将 ViewPager 高度替换为 dp 值,它 "worked"。但是当我替换那些视图时,第一项始终是空白的。但是当我滚动到第三个并返回到第一个时,出于某种原因,项目在那里。
我也不知道身高问题。我在 ViewPager 中有一个函数,它根据列表中最高的 child 来设置它的高度。如果列表是静态的,它可以工作,但是当我刷新它时它现在不工作了。
重新创建整个 ViewPagerAdapter
是解决此问题的方法。
我在 onPageSelected()
中调用了 API 并记住了返回到侦听器函数的位置。
然后我像这样重新创建了整个适配器:
swipePager.apply {
adapter = null
adapter = CustomPagerAdapter(newPages)
adapter?.notifyDataSetChanged()
invalidate()
}
刷新后我滚动到这样记住的位置:
setCurrentItem(position, true)
此解决方案不会留下空白页,但我必须为我的 ViewPager
设置静态高度,这在 mdpi
屏幕上可能是个问题,有时无法重绘特定 dp
XML
布局中的值正确。 Phone 例如 Sony Xperia E5
有这个问题,它有 xhdpi
屏幕,我的 ViewPager
的一部分从底部被裁剪。
对于 mdpi
和 xhdpi
,必须使用单独的 dimens.xml
手动调整。
我有自定义 ViewPager
和 PagerAdapter
,它们正在 instantiateItem
中加载项目。如果我第一次使用设置的项目列表初始化它,它工作正常。
但是当我在列表上调用刷新并且我想用新的(完全不同的)列表填充适配器时,在调用 viewPager.adapter?.notifyDataSetChanged()
之后,PagerAdapter 停止正常工作并且那些项目是没有内容的空白页面,我可以在 UI.
PageScreen
不是 Fragment
。它只是 ViewGroup
容器,它正在膨胀布局并设置特定项目的值。类似于RecyclerView
中的ViewHolder
+ Binder
.
另外 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 中移除并为每个项目调用 instantiateItem()
来正确刷新项目(我希望这是在我调用 notifyDataSetChanged()
时由 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()
}
更新:
我设法 "fix" 通过将 ViewPager 高度设置为固定值而不是 WRAP_CONTENT
但这不是解决方案。我想要具有动态高度的 ViewPager,因为它的一些 children 可以有不同的高度 + 在 Android 中将某些东西设置为静态不是好的方法。一些带有方形显示屏的手机可能会裁剪页面。
发生的事情是当我替换所有项目时,那些 "blank" 页面是高度为 0px 和宽度为 0px 的项目,原因不明。
如果我将 ViewPager 高度替换为 dp 值,它 "worked"。但是当我替换那些视图时,第一项始终是空白的。但是当我滚动到第三个并返回到第一个时,出于某种原因,项目在那里。
我也不知道身高问题。我在 ViewPager 中有一个函数,它根据列表中最高的 child 来设置它的高度。如果列表是静态的,它可以工作,但是当我刷新它时它现在不工作了。
重新创建整个 ViewPagerAdapter
是解决此问题的方法。
我在 onPageSelected()
中调用了 API 并记住了返回到侦听器函数的位置。
然后我像这样重新创建了整个适配器:
swipePager.apply {
adapter = null
adapter = CustomPagerAdapter(newPages)
adapter?.notifyDataSetChanged()
invalidate()
}
刷新后我滚动到这样记住的位置:
setCurrentItem(position, true)
此解决方案不会留下空白页,但我必须为我的 ViewPager
设置静态高度,这在 mdpi
屏幕上可能是个问题,有时无法重绘特定 dp
XML
布局中的值正确。 Phone 例如 Sony Xperia E5
有这个问题,它有 xhdpi
屏幕,我的 ViewPager
的一部分从底部被裁剪。
对于 mdpi
和 xhdpi
,必须使用单独的 dimens.xml
手动调整。