ViewPager不重绘内容,保持/变成空白
ViewPager在这里遇到了一个非常奇怪的问题。 我们在每个ViewPager页面上embedded列表,并在更新列表数据时在列表适配器和视图分页器适配器上触发notifyDataSetChanged。
我们观察到的是,有时,页面不会更新其视图树,即保持空白,或者有时甚至在分页时消失。 当来回分页几次时,内容会突然重现。 这看起来好像Android缺less视图更新。 我还注意到,在使用层次结构查看器进行debugging时,select视图总是会使其重新出现,显然是因为层次结构查看器强制所选视图重绘自己。
我不能编程这个工作,虽然; 无效列表视图,甚至整个视图寻呼机,都没有效果。
这是与compatibility-v4_r7库。 我也尝试使用最新版本,因为它声称修复了与查看寻呼机有关的许多问题,但是更糟糕的是(例如,手势被打破了,所以有时候不会再让我翻遍所有的页面)。
还有其他人遇到这些问题,或者你有什么可能导致这个问题的想法?
我们终于find了解决办法。 显然我们的实施遭遇了两个问题:
- 我们的适配器没有删除
destroyItem()
中的视图。 - 我们正在caching视图,所以我们只需要膨胀我们的布局一次,因为我们没有删除
destroyItem()
的视图,我们没有在instantiateItem()
添加它,而只是返回当前对应的caching视图位置。
我并没有在ViewPager
的源代码中ViewPager
,也没有明确表示你必须这样做 – 但是文档说:
destroyItem()
删除给定位置的页面。 适配器负责从容器中删除视图,尽pipe只能从finishUpdate(ViewGroup)返回的时候确保完成。
和:
一个非常简单的PagerAdapter可以select使用页面视图本身作为关键对象,创build后从instantiateItem(ViewGroup,int)返回,并将它们添加到父ViewGroup。 一个匹配的destroyItem(ViewGroup,int,Object)实现将从父ViewGroup中移除视图,而isViewFromObject(View,Object)可以被实现为返回视图==对象。
所以我的结论是, ViewPager
依赖于它的底层适配器来在instantiateItem()
/ destroyItem()
显式地添加/删除它的子ViewPager
。 也就是说,如果你的适配器是PagerAdapter
的子类,你的子类必须实现这个逻辑。
注意:如果您在ViewPager
使用列表,请注意这 ViewPager
。
如果ViewPager
设置在带有FragmentPagerAdapter的FragmentPagerAdapter
,请使用getChildFragmentManager()
而不是getSupportFragmentManager()
作为参数来初始化您的FragmentPagerAdapter
。
mAdapter = new MyFragmentPagerAdapter(getChildFragmentManager());
代替
mAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager());
我有完全相同的问题,但我实际上销毁了destroyItem中的视图(我认为)。 然而问题是我用viewPager.removeViewAt(index);
销毁了它viewPager.removeViewAt(index);
viewPager.removeView((View) object);
of viewPager.removeView((View) object);
错误:
@Override public void destroyItem(ViewGroup viewPager, int position, Object object) { viewPager.removeViewAt(position); }
对:
@Override public void destroyItem(ViewGroup viewPager, int position, Object object) { viewPager.removeView((View) object); }
ViewPager试图在重复使用物品的时候做一些聪明的事情,但是当事情发生变化时,它需要你返回新的物品位置。 尝试添加到您的PagerAdapter:
public int getItemPosition (Object object) { return POSITION_NONE; }
它基本上告诉ViewPager,一切都改变了(并强制它重新实例化所有东西)。 这是我能想到的唯一的事情。
我有同样的症状的问题,但一个不同的原因,结果是我的一个愚蠢的错误。 以为我会在这里添加它,以防万一它帮助任何人。
我有一个ViewPager使用FragmentStatePagerAdapter过去有两个片段,但我后来又添加了第三个。 但是,我忘记了默认的屏幕页面限制是1 – 所以,当我切换到新的第三个片段时,第一个将被破坏,然后在切换回来之后重新创build。 问题是我的活动负责通知这些片段初始化它们的UI状态。 这发生在活动和片段生命周期相同的情况下工作,但为了解决这个问题,我必须在启动生命周期中更改片段以初始化自己的UI。 最后,我还把setOffscreenPageLimit修改为2,这样所有的三个片段在任何时候都保持活着(在这种情况下是安全的,因为它们不是很强的内存)。
Android支持库有一个演示活动,在每个页面上都包含一个带有ListView的ViewPager。 你应该看一看,看看它是干什么的。
在Eclipse中(使用Android开发工具r20):
- select
New > Android Sample Project
- select您的目标API级别(我build议最新的可用)
- select
Support4Demos
- 右键单击该项目,然后select“
Android Tools > Add Support Library
- 运行应用程序,然后select
Fragment
,然后selectPager
这个代码在src/com.example.android.supportv4.app/FragmentPagerSupport.java
。 祝你好运!
我遇到了这个问题,并有非常类似的问题。 我甚至问过堆栈溢出。
对于我来说,在我的父母父母的视图有人subclassed LinearLayout
和super.requestLayout()
requestLayout()
没有调用super.requestLayout()
。 这阻止了onMeasure
和onLayout
被我的ViewPager调用(尽pipe层次结构查看器手动调用这些)。 没有被测量,他们将在ViewPager中显示为空白。
所以检查你的包含意见。 确保他们从视图的子类,不要盲目覆盖requestLayout或类似的东西。
有相同的问题,这是与ListView
(因为我的空视图显示罚款,如果列表是空的)。 我只是在有问题的ListView
上调用requestLayout()
。 现在画得很好!
在使用ViewPager和FragmentStatePagerAdapter时遇到了同样的问题。 我试着用一个3秒延迟的处理程序来调用invalidate()和requestLayout(),但它不起作用。 什么工作是重置viewPager的背景颜色如下:
MyFragment.java
private Handler mHandler; private Runnable mBugUpdater; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = new ViewPager(getActivity()); //...Create your adapter and set it here... mHandler = new Handler(); mBugUpdater = new Runnable(){ @Override public void run() { mVp.setBackgroundColor(mItem.getBackgroundColor()); mHandler = null; mBugUpdater = null; } }; mHandler.postDelayed(mBugUpdater,50); return rootView; } @Override public void onPause() { if(mHandler != null){ //Remove the callback if it hasn't triggered yet mHandler.removeCallbacks(mBugUpdater); mHandler = null; mBugUpdater = null; } super.onPause(); }
对于我来说,在应用程序被杀后,问题又回到了活动中。 我使用从Android来源修改的自定义视图寻呼机适配器。视图寻呼机直接embedded到活动中。
调用viewPager.setCurrentItem(position, true);
(与animation)后,设置数据和notifyDataSetChanged()似乎工作,但如果参数设置为false它不,并且片段是空白的。 这是一个可能对某人有帮助的边缘案例。
我有类似的问题。 我caching视图,因为我只需要ViewPager
3个视图。 当我向前滑动一切都好,但是当我开始向后滑动发生错误时,它说“我的视图已经有一个父母”。 解决scheme是手动删除不需要的项目。
@Override public Object instantiateItem(ViewGroup container, int position) { int localPos = position % SIZE; TouchImageView view; if (touchImageViews[localPos] != null) { view = touchImageViews[localPos]; } else { view = new TouchImageView(container.getContext()); view.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); touchImageViews[localPos] = view; } view.setImageDrawable(mDataModel.getPhoto(position)); Log.i(IRViewPagerAdpt.class.toString(), "Add view " + view.toString() + " at pos: " + position + " " + localPos); if (view.getParent() == null) { ((ViewPager) container).addView(view); } return view; } @Override public void destroyItem(ViewGroup container, int position, Object view) { // ((ViewPager) container).removeView((View) view); Log.i(IRViewPagerAdpt.class.toString(), "remove view " + view.toString() + " at pos: " + position); } .................. private static final int SIZE = 3; private TouchImageView[] touchImageViews = new TouchImageView[SIZE];