【问题标题】:ViewPager list refresh is not working properlyViewPager 列表刷新无法正常工作
【发布时间】:2020-05-26 09:21:59
【问题描述】:

我有自定义的ViewPagerPagerAdapter,它们在instantiateItem 中加载项目。如果我第一次使用设置的项目列表初始化它,它工作正常。

但是当我在列表上调用刷新并且我想用新的(完全不同的)列表填充适配器时,在调用 viewPager.adapter?.notifyDataSetChanged() 之后,PagerAdapter 停止正常工作并且这些项目是没有内容的空白页面,我可以在它们中滑动用户界面。

PageScreen 不是Fragment。它只是 ViewGroup 容器,它正在膨胀布局并设置特定项目的值。类似于RecyclerView中的ViewHolder + Binder

当我添加新列表并调用notifyDataSetChanged() 时,instatiateItem() 也只被调用一次。开始时它被称为 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() 来正确刷新项目(我希望这是由 PagerAdapter 和 ViewPager 在我调用 notifyDataSetChanged() 时在内部完成的)。但是结果和上面一样。现在每一页都是空白的。 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 中有函数,它根据列表中最高的孩子设置它的高度。如果列表是静态的,它可以工作,但是当我刷新它时它现在不起作用。

【问题讨论】:

    标签: android kotlin android-viewpager android-pageradapter


    【解决方案1】:

    重新创建整个ViewPagerAdapter 是解决此问题的方法。

    我在onPageSelected() 中调用了API,并将记住的位置返回给监听函数。

    然后我像这样重新创建了整个适配器:

    swipePager.apply {
       adapter = null
       adapter = CustomPagerAdapter(newPages)
       adapter?.notifyDataSetChanged()
       invalidate()
    }
    

    刷新后,我滚动到这样记住的位置:

    setCurrentItem(position, true)
    

    此解决方案不会留下空白页,但我必须为我的ViewPager 设置静态高度,这可能是mdpi 屏幕上的问题,有时无法从XML 布局正确重绘特定的dp 值。有此问题的电话是例如Sony Xperia E5,它有xhdpi 屏幕,而我的ViewPager 的一部分是从底部裁剪的。

    这必须使用单独的 dimens.xml 手动调整 mdpixhdpi

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-21
      • 1970-01-01
      • 2017-11-29
      • 2017-01-21
      • 2014-11-03
      相关资源
      最近更新 更多