ViewPager列表刷新无法正常工作

时间:2020-05-26 09:21:59

标签: android kotlin android-viewpager android-pageradapter

我有自定义ViewPagerPagerAdapter,它们正在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内部具有函数,该函数根据列表中的最高子级设置其高度。如果列表是静态的,它可以工作,但是当我刷新它时,它现在不工作。

1 个答案:

答案 0 :(得分:0)

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

我在onPageSelected()内调用了API,并记住了返回给侦听器函数的位置。

然后我重新创建整个适配器,如下所示:

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

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

setCurrentItem(position, true)

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

对于dimens.xmlmdpi,必须分别使用单独的xhdpi进行调整。

相关问题