简体   繁体   English

ViewPager 列表刷新无法正常工作

[英]ViewPager list refresh is not working properly

I have custom ViewPager and PagerAdapter which is loading items inside instantiateItem .我有自定义ViewPagerPagerAdapter ,它们在instantiateItem中加载项目。 It is working fine if I initialize it for the first time with set list of items.如果我第一次使用设置的项目列表初始化它,它工作正常。

But as I call refresh on the list and I want to populate Adapter with new (totally different) list, after calling viewPager.adapter?.notifyDataSetChanged() , PagerAdapter stops working properly and those items are blank pages without content and I can swipe through them in UI.但是当我在列表上调用刷新并且我想用新的(完全不同的)列表填充适配器时,在调用viewPager.adapter?.notifyDataSetChanged()之后,PagerAdapter 停止正常工作并且这些项目是没有内容的空白页面,我可以刷过它们在 UI 中。

PageScreen is not Fragment . PageScreen不是Fragment It is just ViewGroup container which is inflating layout and setting values out of specific item.它只是ViewGroup容器,它正在膨胀布局并从特定项目中设置值。 It is similar to ViewHolder + Binder in RecyclerView .它类似于RecyclerView中的ViewHolder + Binder

Also instatiateItem() is called only once as i add new list and call notifyDataSetChanged() .当我添加新列表并调用notifyDataSetChanged()时,也只调用一次instatiateItem() () 。 At start it is called 3 items, which is amount of PageScreen items in first list.开始时它被称为 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()

Also tried this (same result):也试过这个(同样的结果):

//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() }

Adapter:适配器:

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
    }
}

Also I tried to properly refresh items (I expect that this is done internally by PagerAdapter and ViewPager when I call notifyDataSetChanged() ) by removing them from ViewPager contentView and calling instantiateItem() for each item.我还尝试通过从 ViewPager contentView 中删除它们并为每个项目调用instantiateItem()来正确刷新项目(我希望这是由 PagerAdapter 和 ViewPager 在我调用notifyDataSetChanged()时在内部完成的)。 But same result as above.但是结果和上面一样。 Now every single page was blank.现在每一页都是空白的。 Function below is added to CustomPagerAdapter .下面的 Function 添加到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()
    }

UPDATE: I managed to "fix" this by setting ViewPager height to fixed value instead WRAP_CONTENT but its not a solution.更新:我设法通过将 ViewPager 高度设置为固定值而不是WRAP_CONTENT来“解决”这个问题,但这不是解决方案。 I want ViewPager with dynamic height, because some of its children can have different height + setting something to static is not good approach in Android.我想要具有动态高度的 ViewPager,因为它的一些子项可以有不同的高度 + 设置 static 在 Android 中不是好方法。 Some phones with square displays could have cropped page then.一些带有方形显示屏的手机可能会裁剪页面。

What happened is as I replaced all items, those "blank" pages were items with 0px height and 0px width for some unknown reason.发生的事情是当我替换所有项目时,那些“空白”页面是具有 0px 高度和 0px 宽度的项目,原因不明。

If I replaced ViewPager height to dp value, it "worked".如果我将 ViewPager 高度替换为 dp 值,它“有效”。 But as I replaced those Views, first item was always blank.但是当我替换那些视图时,第一项总是空白。 but as I scrolled to third one and back to first, item was there for some reason.但是当我滚动到第三个并返回到第一个时,项目出于某种原因在那里。

Also I don't get that height problem.我也没有得到那个高度的问题。 I have function inside ViewPager which is setting its height based on tallest child in list.我在 ViewPager 中有 function ,它根据列表中最高的孩子设置其高度。 It works if list is static, but it is not working now as I refresh that.如果列表是 static,它可以工作,但是当我刷新它时它现在不起作用。

Recreating whole ViewPagerAdapter is a solution for this problem.重新创建整个ViewPagerAdapter是解决此问题的方法。

I called API inside onPageSelected() and remembered position returned to listener function.我在onPageSelected()中调用了 API 并记得 position 返回到监听器 function。

Then I recreated whole adapter like this:然后我像这样重新创建了整个适配器:

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

and after refresh I scrolled to remembered position like this:刷新后,我滚动到记住 position ,如下所示:

setCurrentItem(position, true)

This solution will not left blank pages, but I had to set static height for my ViewPager , which can be a problem on mdpi screens which sometimes cannot redraw particular dp value from XML layout correctly.此解决方案不会留下空白页,但我必须为我的ViewPager设置 static 高度,这可能是mdpi屏幕上的问题,有时无法从XML布局正确重绘特定的dp值。 Phone with this problem is for example Sony Xperia E5 which has xhdpi screen and part of my ViewPager is cropped from the bottom.有这个问题的手机是Sony Xperia E5 ,它有xhdpi屏幕,我的ViewPager的一部分是从底部裁剪的。

This have to be tuned manually with separate dimens.xml for both mdpi and xhdpi .这必须使用单独的dimens.xml手动调整mdpixhdpi

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM