使用FragmentStatePageAdapter
时,我会得到这样的片段:
@Override
public Fragment getItem(int position) {
return new SuperCoolFragment();
}
然而,稍后我的代码我需要找到这个片段来设置属性。在应用程序的其他部分,我使用片段我基本上标记它们并使用findFragmentByTag(TAG)
查找它们,但现在我不知道该怎么做。
如何使用FragmentStatePageAdapter
找到片段?
答案 0 :(得分:46)
*编辑*
@ElliotM指出,有一个更好的解决方案。无需更改适配器中的任何内容,只需获取片段:
Fragment myFragment = (Fragment) adapter.instantiateItem(viewPager, viewPager.getCurrentItem());
*旧解决方案*
最佳选择是第二个解决方案: http://tamsler.blogspot.nl/2011/11/android-viewpager-and-fragments-part-ii.html
简而言之:您可以跟踪所有“活动”片段页面。在这种情况下,您将跟踪ViewPager使用的FragmentStatePagerAdapter中的片段页面。
public Fragment getItem(int index) {
Fragment myFragment = MyFragment.newInstance();
mPageReferenceMap.put(index, myFragment);
return myFragment;
}
为了避免保留对“非活动”片段页面的引用,我们需要实现FragmentStatePagerAdapter的destroyItem(...)方法:
public void destroyItem(View container, int position, Object object) {
super.destroyItem(container, position, object);
mPageReferenceMap.remove(position);
}
...当您需要访问当前可见的页面时,请调用:
int index = mViewPager.getCurrentItem();
MyAdapter adapter = ((MyAdapter)mViewPager.getAdapter());
MyFragment fragment = adapter.getFragment(index);
... MyAdapter的getFragment(int)方法如下所示:
public MyFragment getFragment(int key) {
return mPageReferenceMap.get(key);
}
---编辑:
同样在适配器中添加此内容,以便在更改方向后添加:
/**
* After an orientation change, the fragments are saved in the adapter, and
* I don't want to double save them: I will retrieve them and put them in my
* list again here.
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
MyFragment fragment = (MyFragment) super.instantiateItem(container,
position);
mPageReferenceMap.put(position, fragment);
return fragment;
}
答案 1 :(得分:15)
我找到了另一种方法,不确定使用它是否有任何问题,对我来说似乎没问题。
我正在检查 FragmentStatePageAdapter 的代码,我看到了这个方法:
@Override
52 public Object More ...instantiateItem(View container, int position) {
53 // If we already have this item instantiated, there is nothing
54 // to do. This can happen when we are restoring the entire pager
55 // from its saved state, where the fragment manager has already
56 // taken care of restoring the fragments we previously had instantiated.
57 if (mFragments.size() > position) {
58 Fragment f = mFragments.get(position);
59 if (f != null) {
60 return f;
61 }
62 }
63
64 if (mCurTransaction == null) {
65 mCurTransaction = mFragmentManager.beginTransaction();
66 }
67
68 Fragment fragment = getItem(position);
69 if (DEBUG) Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
70 if (mSavedState.size() > position) {
71 Fragment.SavedState fss = mSavedState.get(position);
72 if (fss != null) {
73 fragment.setInitialSavedState(fss);
74 }
75 }
76 while (mFragments.size() <= position) {
77 mFragments.add(null);
78 }
79 fragment.setMenuVisibility(false);
80 mFragments.set(position, fragment);
81 mCurTransaction.add(container.getId(), fragment);
82
83 return fragment;
84 }
您可以使用此方法获取已为该特定位置设置的片段。所以如果你想让Fragment在第1位,你只需要打电话:
myFragmentStatePageAdpater.instantiateItem(null, 1)
希望有所帮助
答案 2 :(得分:5)
我通过向getItemTag(int position)
添加FragmentStatePagerAdapter
函数来实现此目的。如果有其他人想要使用此路线,则更新文件的插入版本为here。
答案 3 :(得分:2)
如果重新创建活动,在getItem()方法中将片段存储到HashMap的解决方案不起作用!
问题是,FragmentStatePagerAdapter的默认实现直接从FragmentManager恢复片段而不调用getItem()方法。这意味着您永远不会有机会存储对片段的引用。
有关详细信息,请参阅源代码: FragmentStatePagerAdapter#restoreState
这基本上意味着获取片段引用的唯一方法是使用反射。如果您使用支持库,这是相对 * 安全 **。
以下是:
@SuppressWarnings("unchecked")
public Fragment getFragment(int position) {
try {
Field f = FragmentStatePagerAdapter.class.getDeclaredField("mFragments");
f.setAccessible(true);
ArrayList<Fragment> fragments = (ArrayList<Fragment>) f.get(this);
if (fragments.size() > position) {
return fragments.get(position);
}
return null;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
相对 *意味着它不像在框架类上使用反射那样危险。支持类被编译到您的应用程序中,此代码无法在您的设备上运行,但会在其他设备上崩溃。您仍然可以通过将支持库更新到更新版本来破坏此解决方案
安全 **使用反射永远不会安全;但是,当您使用的库存在设计缺陷时,您必须使用此方法。
答案 4 :(得分:1)
正如@Lancelot所提到的,你可以调用并将结果转换为你的SuperCoolFragment:
SuperCoolFragment frag = (SuperCoolFragment) yourFragmentStatePageAdpater.instantiateItem(null, position);
答案 5 :(得分:0)
我尝试了Frank的答案,建议使用其中链接的教程中的第二种方法,机器人因为某种原因将方法getFragment()添加到我的ViewPagerAdapter后,我无法通过mViewPager.getAdapter访问它。 getFragment ()好像它不存在,所以我将mPageReferenceMap声明从ViewPagerAdapter移动到封闭类,因此可以从封闭类的任何一点(在我的例子中是MainActivity的其他片段的回调方法)轻松访问它,最终使可以在片段之间传递数据。 感谢弗兰克,如果你喜欢我,可以随意使用我的夹具来解决访问自定义getFragment方法的问题。
答案 6 :(得分:0)
另一种解决方案是复制粘贴FragmentStatePagerAdapter的源代码并添加getFragment
方法:
public Fragment getFragment(int position) {
if (position >= mFragments.size()) {
return null;
}
return mFragments.get(position);
}
答案 7 :(得分:0)
覆盖setPrimaryItem
,并使用该位置,它将是正确的页面索引:
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container,position,object);
if (position == 1) {
currentPageIndex=cameraFragment.pageIndex;
}
答案 8 :(得分:-10)
创建一个持有者来保存新的SuperCoolFragment对象。然后标记并返回持有者对象。
@Override
public Fragment getItem(int position) {
SuperCoolFragment superCoolFragment = new SuperCoolFragment();
superCoolFragment.setTag(YOUR_TAG);
return superCoolFragment;
}