我正在使用Android中的v4兼容性ViewPager . 我的FragmentActivity有一堆数据,可以在我的ViewPager中的不同页面上以不同的方式显示 . 到目前为止,我只有3个相同的ListFragment实例,但将来我将有3个不同的ListFragments实例 . ViewPager位于垂直电话屏幕上,列表不是并排的 .
现在,ListFragment上的一个按钮启动一个单独的整页活动(通过FragmentActivity),它返回并且FragmentActivity修改数据,保存数据,然后尝试更新其ViewPager中的所有视图 . 就在这里,我被卡住了 .
public class ProgressMainActivity extends FragmentActivity
{
MyAdapter mAdapter;
ViewPager mPager;
@Override
public void onCreate(Bundle savedInstanceState)
{
...
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager) findViewById(R.id.viewpager);
mPager.setAdapter(mAdapter);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
...
updateFragments();
...
}
public void updateFragments()
{
//Attempt 1:
//mAdapter.notifyDataSetChanged();
//mPager.setAdapter(mAdapter);
//Attempt 2:
//HomeListFragment fragment = (HomeListFragment) getSupportFragmentManager().findFragmentById(mAdapter.fragId[0]);
//fragment.updateDisplay();
}
public static class MyAdapter extends FragmentPagerAdapter implements
TitleProvider
{
int[] fragId = {0,0,0,0,0};
public MyAdapter(FragmentManager fm)
{
super(fm);
}
@Override
public String getTitle(int position){
return titles[position];
}
@Override
public int getCount(){
return titles.length;
}
@Override
public Fragment getItem(int position)
{
Fragment frag = HomeListFragment.newInstance(position);
//Attempt 2:
//fragId[position] = frag.getId();
return frag;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE; //To make notifyDataSetChanged() do something
}
}
public class HomeListFragment extends ListFragment
{
...
public static HomeListFragment newInstance(int num)
{
HomeListFragment f = new HomeListFragment();
...
return f;
}
...
现在你可以看到,我的第一次尝试是整个FragmentPagerAdapter上的notifyDataSetChanged,这有时会显示更新数据,但是其他人我得到了IllegalStateException:在onSaveInstanceState之后无法执行此操作 .
我的第二次尝试调用我的ListFragment中调用更新函数,但getItem中的getId返回0.根据我尝试过的文档
使用findFragmentById()或findFragmentByTag()从FragmentManager获取对Fragment的引用
但我不知道我的碎片的标签或ID!我有一个用于ViewPager的android:id =“@ id / viewpager”,以及一个用于ListFragment布局中我的ListView的android:id =“@ android:id / list”,但我不认为这些是有用的 .
那么,我怎么能:a)一次性安全地更新整个ViewPager(理想情况下将用户返回到之前的页面) - 用户可以看到视图更改 . 或者最好是,b)在每个受影响的ListFragment中调用一个函数来手动更新ListView .
任何帮助都将被感激地接受!
10 回答
每次实例化Fragement时尝试记录标记 .
Barkside的答案适用于
FragmentPagerAdapter
,但不适用于FragmentStatePagerAdapter
,因为它没有在传递给FragmentManager
的片段上设置标签 .使用
FragmentStatePagerAdapter
似乎我们可以使用instantiateItem(ViewGroup container, int position)
调用 . 它返回位于position
位置的片段的引用 . 如果FragmentStatePagerAdapter
已经存在对相关片段的引用,instantiateItem
只返回对该片段的引用,并且不会再调用getItem()
来实例化它 .所以,假设我正在查看片段#50,并希望访问片段#49 . 由于它们很接近,#49很可能已经被实例化 . 所以,
好吧,我想我会分享其他人的利益 . ViewPager中的片段标记采用
"android:switcher:VIEWPAGER_ID:INDEX"
格式,其中VIEWPAGER_ID
是XML布局中的R.id.viewpager
,INDEX是viewpager中的位置 . 因此,如果位置已知(例如0),我可以在updateFragments()
中执行:我不知道这是否是一种有效的方式,但它会做到更好的建议 .
如果你问我,下面的第二个解决方案,跟踪所有"active"片段页面,更好:http://tamsler.blogspot.nl/2011/11/android-viewpager-and-fragments-part-ii.html
来自barkside的答案对我来说太难了 .
您可以跟踪所有“活动”片段页面 . 在这种情况下,您将跟踪ViewPager使用的FragmentStatePagerAdapter中的片段页面 .
为了避免保留对“非活动”片段页面的引用,我们需要实现FragmentStatePagerAdapter的destroyItem(...)方法:
...当您需要访问当前可见的页面时,您可以调用:
... MyAdapter的getFragment(int)方法如下所示:
“
好的,在上面的@barkside测试方法后,我无法使用我的应用程序 . 然后我记得IOSched2012 app也使用
viewpager
,这就是我找到解决方案的地方 . 它不使用任何片段ID或标签,因为这些不是由viewpager
以易于访问的方式存储的 .这是来自IOSched应用程序HomeActivity的important parts . 要特别注意 comment ,其中有关键:
并将
Fragments
中的实例存储在_1077612中,如下所示:另外,请记住像这样保护你的
Fragment
电话:您可以复制
FragmentPagerAdapter
并修改一些源代码,添加getTag()
方法例如
然后扩展它,覆盖这些抽象方法,不需要害怕Android Group的改变
FragmentPageAdapter
将来的源代码也没有问题的工作:
页面片段布局中的某个位置:
在片段的onCreateView()中:
以及从ViewPager返回Fragment的方法(如果存在):
或者,您可以像这样覆盖
setPrimaryItem
中的setPrimaryItem
方法:我想提出我的方法,以防它可以帮助其他人:
这是我的寻呼机适配器:
在我的活动中,我有:
然后获取当前片段我所做的是:
这是我的解决方案,因为我不需要跟踪我的标签,无论如何都需要刷新它们 .