首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >从ViewPager检索片段

从ViewPager检索片段
EN

Stack Overflow用户
提问于 2012-01-09 15:38:38
回答 23查看 152.8K关注 0票数 252

我结合使用ViewPagerFragmentStatePagerAdapter来托管三个不同的片段:

  • Fragment1
  • Fragment2
  • Fragment3

当我想要从FragmentActivity中的ViewPager获取Fragment1时。

问题出在哪里?我该如何解决?

EN

回答 23

Stack Overflow用户

发布于 2013-03-07 08:52:32

主要答案依赖于框架生成的名称。如果这一点发生变化,那么它将不再有效。

这个解决方案如何,覆盖您的Fragment(State)PagerAdapterinstantiateItem()destroyItem()

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);
    }
}

在处理可用的片段时,这似乎对我很有效。尚未实例化的片段,在调用getRegisteredFragment时将返回null。但我主要使用它来从ViewPageradapater.getRegisteredFragment(viewPager.getCurrentItem())中获取当前的Fragment,它不会返回null

我没有意识到这种解决方案的任何其他缺点。如果有的话,我想知道。

票数 507
EN

Stack Overflow用户

发布于 2014-07-10 03:17:46

对于从ViewPager中抓取片段,在这里和其他相关的SO线程/博客上有很多答案。我见过的每个人都是破产的,他们通常似乎属于下面列出的两种类型之一。如果你只想获取当前片段,还有一些其他有效的解决方案,比如这个线程上的this other answer。

如果使用FragmentPagerAdapter,请参见下面的内容。如果使用FragmentStatePagerAdapter,那么值得去看看。抓取不是FragmentStateAdapter中当前索引的索引并不是那么有用,因为从本质上讲,这些索引将被完全删除,并且超出了offScreenLimit的范围。

不快乐的路径

错误:维护您自己的内部片段列表,并在调用 FragmentPagerAdapter.getItem() 时添加到

  • 通常使用SparseArrayMap
  • Not,这是我见过的许多说明生命周期事件的示例之一,所以这个解决方案很脆弱。由于getItem仅在页面第一次在ViewPager中滚动到(或如果ViewPager.setOffscreenPageLimit(x) > 0)时调用,如果宿主Activity / Fragment被终止或重新启动,则在重新创建自定义SpaseArray时内部FragmentPagerActivity将被清除,但在幕后将重新创建ViewPagers内部片段,并且getItem将不会对任何索引调用,因此从索引中获取片段的能力将永远丢失。你可以通过FragmentManager.getFragment()putFragment保存和恢复这些片段引用来解决这个问题,但是这开始变得混乱了。

错误:构造您自己的标记id,与 FragmentPagerAdapter中使用的标记id匹配,并使用它从FragmentManager中检索页面片段

  • 这更好,因为它解决了第一个内部数组解决方案中丢失片段引用的问题,但正如上面的答案和网上其他地方正确地指出的那样-它感觉很粗糙,因为它是ViewPager内部的私有方法,可以随时更改或针对任何操作系统版本。

为这个解决方案重新创建的方法是

private static String makeFragmentName(int viewId, long id) {
    return "android:switcher:" + viewId + ":" + id;
}

A HAPPY PATH: ViewPager.instantiateItem()

与上面的 getItem() 类似,但不破坏生命周期的是挂接到instantiateItem()中,而不是getItem()中,因为每次创建/访问索引时都会调用前者。请参阅this answer

快乐之路:构建您自己的 FragmentViewPager

source of the latest support lib构造您自己的FragmentViewPager类,并在内部更改用于生成片段标记的方法。你可以用下面的代码替换它。这样做的好处是你知道标签的创建永远不会改变,而且你不需要依赖私有的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;
}

然后,正如文档所说,当您想获取用于索引的片段时,只需调用类似此方法的方法(您可以将其放入自定义FragmentPagerAdapter或子类中),要知道,如果尚未为该页面调用,即尚未创建该页面,则结果可能为空getItem。

/**
 * @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;
}

这是一个简单的解决方案,解决了web上随处可见的其他两个解决方案中的问题。

票数 85
EN

Stack Overflow用户

发布于 2012-02-15 20:17:19

将下一个方法添加到您的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;
}

getActiveFragment(0)必须工作。

以下是在ViewPager https://gist.github.com/jacek-marchwicki/d6320ba9a910c514424d中实施的解决方案。如果出现故障,您将看到良好的崩溃日志。

票数 70
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8785221

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档