ViewPager列表刷新无法正常工作

问题描述 投票:0回答:1

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

android kotlin android-viewpager android-pageradapter
1个回答
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.xmlmdpi,必须分别使用xhdpi进行手动调整。

© www.soinside.com 2019 - 2024. All rights reserved.