Qun*_*Qin 240 android android-fragments android-viewpager
我使用的是ViewPager连同FragmentStatePagerAdapter主办三个不同的片段:
当我想Fragment1从ViewPager在FragmentActivity.
有什么问题,我该如何解决?
Str*_*ton 499
主要答案依赖于框架生成的名称.如果这种情况发生了变化,那么它将不再起作用.
这个怎么样的解决方案,覆盖instantiateItem()和destroyItem()你的Fragment(State)PagerAdapter:
public class MyPagerAdapter extends FragmentStatePagerAdapter {
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
return ...;
}
@Override
public Fragment getItem(int position) {
return MyFragment.newInstance(...);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
}
Run Code Online (Sandbox Code Playgroud)
在处理可用的碎片时,这似乎对我有用.尚未实例化的片段在调用时将返回null getRegisteredFragment.但我一直在使用这主要是为了获取当前Fragment出的ViewPager:adapater.getRegisteredFragment(viewPager.getCurrentItem())这将不会返回null.
我不知道这个解决方案的任何其他缺点.如果有的话,我想知道.
Dor*_*ori 85
为了从ViewPager中抓取片段,这里和其他相关的SO线程/博客上有很多答案.我见过的每个人都被打破了,他们通常似乎属于下面列出的两种类型之一.还有一些其他的解决方案有效,如果你只想要抓住当前片段,像这样在此线程的其他答案.
如果使用FragmentPagerAdapter见下文.如果用FragmentStatePagerAdapter它值得看这个.在FragmentStateAdapter中抓取不是当前索引的索引并不像它的性质那样有用,这些索引将完全拆除掉在offScreenLimit边界之外.
错误:维护您自己的内部片段列表,添加到FragmentPagerAdapter.getItem()调用时
SparseArray或MapgetItem只是第一次将页面滚动到(或者如果你的ViewPager.setOffscreenPageLimit(x)> 0 获得)ViewPager,如果托管Activity/ Fragment被杀死或重新启动,那么SpaseArray当重新创建自定义FragmentPagerActivity时内部将被清除,但是在幕后ViewPagers内部片段将被重新创建,并且getItem将不被要求任何的指标,所以从指数得到片段的能力将永远消失.您可以通过保存和恢复这些片段引用来解决这个问题FragmentManager.getFragment(), putFragment但这开始变得混乱恕我直言.错误:构建您自己的标签ID,匹配引擎盖下使用的标签ID,FragmentPagerAdapter并使用它来检索页面碎片FragmentManager
ViewPager可以随时更改或任何操作系统版本.为此解决方案重新创建的方法是
private static String makeFragmentName(int viewId, long id) {
return "android:switcher:" + viewId + ":" + id;
}
Run Code Online (Sandbox Code Playgroud)
ViewPager.instantiateItem()对于getItem()上面但非生命周期中断的类似方法是,这是钩入instantiateItem()而不是getItem()因为每次创建/访问索引时都会调用前者.看到这个答案
FragmentViewPagerFragmentViewPager从最新支持lib的源代码构造您自己的类,并更改内部使用的方法以生成片段标记.您可以使用以下内容替换它.这样做的好处是,您知道标签创建永远不会改变,并且您不依赖于私有API /方法,这总是很危险的.
/**
* @param containerViewId the ViewPager this adapter is being supplied to
* @param id pass in getItemId(position) as this is whats used internally in this class
* @return the tag used for this pages fragment
*/
public static String makeFragmentName(int containerViewId, long id) {
return "android:switcher:" + containerViewId + ":" + id;
}
Run Code Online (Sandbox Code Playgroud)
然后正如文档所说,当你想要获取用于索引的片段时,只需调用类似于此方法的东西(可以放入自定义FragmentPagerAdapter或子类中),如果尚未调用getItem,则可以知道结果可能为null该页面即尚未创建.
/**
* @return may return null if the fragment has not been instantiated yet for that position - this depends on if the fragment has been viewed
* yet OR is a sibling covered by {@link android.support.v4.view.ViewPager#setOffscreenPageLimit(int)}. Can use this to call methods on
* the current positions fragment.
*/
public @Nullable Fragment getFragmentForPosition(int position)
{
String tag = makeFragmentName(mViewPager.getId(), getItemId(position));
Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag);
return fragment;
}
Run Code Online (Sandbox Code Playgroud)
这是一个简单的解决方案,可以解决网络上随处可见的其他两种解决方案中的问题
kzo*_*tin 70
将以下方法添加到FragmentPagerAdapter:
public Fragment getActiveFragment(ViewPager container, int position) {
String name = makeFragmentName(container.getId(), position);
return mFragmentManager.findFragmentByTag(name);
}
private static String makeFragmentName(int viewId, int index) {
return "android:switcher:" + viewId + ":" + index;
}
Run Code Online (Sandbox Code Playgroud)
getActiveFragment(0)必须工作.
以下是ViewPager中实现的解决方案https://gist.github.com/jacek-marchwicki/d6320ba9a910c514424d.如果出现故障,您将看到良好的崩溃日志.
小智 38
另一个简单的解决
public class MyPagerAdapter extends FragmentPagerAdapter {
private Fragment mCurrentFragment;
public Fragment getCurrentFragment() {
return mCurrentFragment;
}
//...
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
if (getCurrentFragment() != object) {
mCurrentFragment = ((Fragment) object);
}
super.setPrimaryItem(container, position, object);
}
}
Run Code Online (Sandbox Code Playgroud)
Ste*_*yle 21
我知道这有几个答案,但也许这会对某人有所帮助.当我需要得到一个Fragment来自我的时候,我使用了一个相对简单的解决方案ViewPager.在您持有Activity或Fragment持有时ViewPager,您可以使用此代码循环每个Fragment持有.
FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
Fragment viewPagerFragment = fragmentPagerAdapter.getItem(i);
if(viewPagerFragment != null) {
// Do something with your Fragment
// Check viewPagerFragment.isResumed() if you intend on interacting with any views.
}
}
Run Code Online (Sandbox Code Playgroud)
如果你知道你的位置Fragment在ViewPager,你可以调用getItem(knownPosition).
如果你不知道你的位置Fragment在ViewPager,你可以有你的孩子Fragments实现与像一个方法的接口getUniqueId(),并用它来区分它们.或者你可以遍历所有Fragments并检查类类型,例如if(viewPagerFragment instanceof FragmentClassYouWant)
!编辑!!!
我发现,getItem只有获得由被称为FragmentPagerAdapter每当Fragment需要创建的第一次,在此之后,它会出现在Fragments使用被回收FragmentManager.这样,FragmentPagerAdapter创建新的 Fragment s的许多实现getItem.使用我的上述方法,这意味着我们将Fragment在每次getItem调用时创建新的s,因为我们遍历了所有项目FragmentPagerAdapter.因此,我找到了一种更好的方法,使用它FragmentManager来获取每个Fragment(使用接受的答案).这是一个更完整的解决方案,并且一直很适合我.
FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
String name = makeFragmentName(mViewPager.getId(), i);
Fragment viewPagerFragment = getChildFragmentManager().findFragmentByTag(name);
// OR Fragment viewPagerFragment = getFragmentManager().findFragmentByTag(name);
if(viewPagerFragment != null) {
// Do something with your Fragment
if (viewPagerFragment.isResumed()) {
// Interact with any views/data that must be alive
}
else {
// Flag something for update later, when this viewPagerFragment
// returns to onResume
}
}
}
Run Code Online (Sandbox Code Playgroud)
你需要这种方法.
private static String makeFragmentName(int viewId, int position) {
return "android:switcher:" + viewId + ":" + position;
}
Run Code Online (Sandbox Code Playgroud)
小智 10
就我而言,上述解决方案均无效.
但是,由于我在Fragment中使用Child Fragment Manager,因此使用了以下内容:
Fragment f = getChildFragmentManager().getFragments().get(viewPager.getCurrentItem());
这仅在Manager中的片段对应于viewpager项时才有效.
为了从ViewPager获取当前的Visible片段.我正在使用这个简单的声明,它工作正常.
public Fragment getFragmentFromViewpager()
{
return ((Fragment) (mAdapter.instantiateItem(mViewPager, mViewPager.getCurrentItem())));
}
Run Code Online (Sandbox Code Playgroud)
我找不到一种简单、干净的方法来做到这一点。但是, ViewPager 小部件只是另一个 ViewGroup ,它托管您的片段。ViewPager 将这些片段作为直接子片段。因此,您可以迭代它们(使用 .getChildCount() 和 .getChildAt() ),并查看您正在查找的片段实例当前是否已加载到 ViewPager 中并获取对其的引用。例如,您可以使用一些静态唯一 ID 字段来区分片段。
请注意,ViewPager 可能尚未加载您正在查找的片段,因为它是像 ListView 一样的虚拟化容器。
| 归档时间: |
|
| 查看次数: |
145380 次 |
| 最近记录: |