ViewPager不重绘内容,保持/变为空白

Mat*_*ias 84 android android-viewpager

我们在这里遇到了一个非常奇怪的ViewPager问题.我们在每个ViewPager页面上嵌入了列表,并在更新列表数据时在列表适配器和视图寻呼机适配器上触发notifyDataSetChanged.

我们观察到的是,有时候,页面不会更新其视图树,即保持空白,或者有时甚至在分页时消失.来回寻呼几次时,内容会突然重新出现.似乎Android在这里缺少视图更新.我还注意到,在使用层次结构查看器进行调试时,选择一个视图将始终使其重新出现,这显然是因为层次结构查看器强制所选视图重绘自身.

我不能以编程方式完成这项工作; 使列表视图无效,甚至整个视图寻呼机都无效.

这与compatibility-v4_r7库有关.我也尝试使用最新版本,因为它声称修复了与查看寻呼机相关的许多问题,但它更糟糕的是(例如,手势被打破,以至于它不会让我不再遍历所有页面.)

是否还有其他人遇到这些问题,或者您是否知道可能导致此问题的原因?

小智 55

如果在ViewPager带有a的Fragment中设置FragmentPagerAdapter,则使用getChildFragmentManager()而不是getSupportFragmentManager()作为参数初始化你的FragmentPagerAdapter.

mAdapter = new MyFragmentPagerAdapter(getChildFragmentManager());
Run Code Online (Sandbox Code Playgroud)

代替

mAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager());
Run Code Online (Sandbox Code Playgroud)

  • 很好的捕获,它似乎解决了我使用FragmentPagerAdapter时的问题 (2认同)
  • 奇迹般有效。应该是公认的答案。 (2认同)

fut*_*sta 44

我们终于设法找到了解决方案.显然我们的实施遇到了两个问题:

  1. 我们的适配器没有删除视图destroyItem().
  2. 我们正在缓存视图,因此我们只需要对布局进行一次膨胀,并且由于我们没有删除视图destroyItem(),因此我们没有添加它,instantiateItem()只是返回对应于当前位置的缓存视图.

我没有太深入地看待ViewPager它的源代码- 而且你必须这样做并不完全明确 - 但文档说:

destroyItem()
删除给定位置的页面.适配器负责从容器中删除视图,但它必须确保在从finishUpdate(ViewGroup)返回时完成此操作.

和:

一个非常简单的PagerAdapter可以选择使用页面视图本身作为关键对象,在创建后从instantiateItem(ViewGroup,int)返回它们并将它们添加到父ViewGroup.匹配的destroyItem(ViewGroup,int,Object)实现将从父ViewGroup中删除View,而isViewFromObject(View,Object)可以实现为return view == object;.

所以我的结论是ViewPager依赖于它的底层适配器在instantiateItem()/中显式添加/删除它的子节点destroyItem().也就是说,如果您的适配器是其子类PagerAdapter,则您的子类必须实现此逻辑.

附注:如果你在里面使用列表,请注意这一点ViewPager.

  • 也可能是问题,是有人使用getFragmentManger而不是GetChildFragmentManager (14认同)
  • 我有同样的问题,但有FragmentPagerAdapter,它为我处理onDestroy.这里没有其他解决方案也可以工作. (2认同)

小智 21

我有完全相同的问题,但实际上我在destroyItem中销毁了视图(我想).然而问题是我使用viewPager.removeViewAt(index);insted 销毁了它viewPager.removeView((View) object);

错误:

@Override
public void destroyItem(ViewGroup viewPager, int position, Object object) {
    viewPager.removeViewAt(position);
}
Run Code Online (Sandbox Code Playgroud)

对:

@Override
public void destroyItem(ViewGroup viewPager, int position, Object object) {
    viewPager.removeView((View) object);
}
Run Code Online (Sandbox Code Playgroud)

  • 这对我有用,但是你知道为什么第一个是问题吗? (2认同)
  • 不适合我:无法将视图转换为片段.这里的对象是一个片段. (2认同)

Chr*_*nes 9

ViewPager试图在重复使用项目时做一些聪明的事情,但它要求你在事情发生变化时返回新的项目位置.尝试将此添加到您的PagerAdapter:

public int getItemPosition (Object object) { return POSITION_NONE; }
Run Code Online (Sandbox Code Playgroud)

它基本上告诉ViewPager所有内容都已更改(并强制它重新实例化所有内容).这是我能想到的唯一一件事.