从 ViewPager 中检索片段

Posted

技术标签:

【中文标题】从 ViewPager 中检索片段【英文标题】:Retrieve a Fragment from a ViewPager 【发布时间】:2012-02-05 19:10:35 【问题描述】:

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

[片段1] [片段2] [片段3]

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

什么是问题,我该如何解决?

【问题讨论】:

【参考方案1】:

主要答案取决于框架生成的名称。如果这种情况发生变化,那么它将不再起作用。

这个解决方案怎么样,覆盖你的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。但我一直使用它主要是为了从ViewPager 中获取当前的Fragmentadapater.getRegisteredFragment(viewPager.getCurrentItem()),这不会返回null

我不知道此解决方案的任何其他缺点。如果有的话,我想知道。

【讨论】:

这也是我能想到的最佳解决方案。唯一的建议是将Fragment 包装在WeakReference 中,以保证您不会阻止被破坏的片段被垃圾收集?这似乎是正确的做法...... MyPagerAdapter 因生命周期而被销毁(即旋转)时会发生什么,registerdFragments 不会丢失吗?使用MyPagerAdapterActivity/Fragment 是否必须将其保存在onSaveInstanceState 中,然后需要使用新的FragmentManager ref 对其进行更新? 如果我没记错的话(你应该检查一下),getItem 方法不会被调用 - 如你所知 - 但 instanceiteItem 方法会为框架恢复后的每个 Fragment 调用轮换。 是的,我已经验证 getItem 不会在轮换时再次被调用(对于任何已经创建的片段),因为 FragmentManager 恢复了它在寻呼机。如果在每个Fragment 恢复时调用instantiateItem,那么这个解决方案实际上比我的或接受的答案更安全,更面向未来。我会考虑自己尝试一下。 @Dori 我不会破坏它。我的解决方案没有使用“getItem()”调用的结果。相反,它使用从“instantiateItem()”调用中存储的结果。并且片段的生命周期没有被破坏,因为存储的片段将在“destroyItem()”调用时从稀疏数组中删除。【参考方案2】:

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

如果使用 FragmentPagerAdapter,请参见下文。如果使用 FragmentStatePagerAdapter 值得关注this。在 FragmentStateAdapter 中抓取不是当前索引的索引并不像它的本质那样有用,这些索引将被完全拆除,超出视野/超出 offScreenLimit 范围。

不快乐的道路

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

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

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

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

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

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

快乐之路: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 或子类中)并意识到结果可能是null 如果尚未为该页面调用 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;

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

【讨论】:

这将起作用,但它需要将 ViewPager 类复制到您自己的源代码中。依靠 ViewPager 的寻呼机适配器的 'instantiateItem()' 和 'destroyItem()' 将起作用,并将遵守片段的生命周期(当从保存的实例状态创建片段时,也会调用这两种方法)。你是对的,依赖 'getItem()' 被调用不是一个好主意,使用私有 API 也不是。 +1 我同意这也是一个解决方案,并在上面进行了编辑。唯一的区别是,上述方法在另一个用例中工作,instantiateItem() 是当您想要访问尚未访问的片段在发生生命周期事件之后并且在生命周期事件之前被访问过。我知道的一个小差异,但它导致了我的程序中的一个微妙的错误,因此我正在研究这个。 如果 setOffscreenPageLimit=1(默认),FragmentStatePageAdapter 将在访问视图页时开始将片段交换进内存和换出内存。通过调用 getItem() 将创建重新访问的页面/片段的新实例。在这种重新访问时,有没有办法指示系统恢复以前创建的实例,而不是创建一个新实例? 如果超出页面限制,它将不得不创建一个新页面 - 但会以保存状态传递。如果想保留旧的,则可以增加页面限制 @Dori FragmentStatePagerAdapter 里面没有getItemId(pos)【参考方案3】:

将下一个方法添加到您的 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 中实现的解决方案。如果出现故障,您将看到良好的崩溃日志。

【讨论】:

非常感谢:)。通过我以另一种方式解决它,我使用处理程序发布片段。这不是很合适,但它最终解决了问题。顺便说一句,你很好:) 我正在使用这种方法,但我相信当我迁移到 API 17 (?) 时它会停止工作。我会推荐另一种方法,如果 Google 只是发布一个 API 来从 ViewPager 中检索片段,我会更喜欢它,因为它的位置。 我在调用第二个片段时遇到问题,该方法创建一个新片段 由于某些 API 版本 makeFragmentName 方法被更改为 private static String makeFragmentName(int viewId, long id) return "android:switcher:" + viewId + ":" + id;因此 getActiveFragment 方法现在应该如下所示(使用 getItemId 而不是 position 作为第二个参数) public Fragment getActiveFragment(ViewPager container, int position) String name = makeFragmentName(container.getId(), getItemId(position));返回 mFragmentManager.findFragmentByTag(name); 它确实有效,但它真的很危险,因为它依赖于视图寻呼机的内部实现,如果谷歌会改变实现(他们可以)坏事就会发生。我真的希望 goole 能提供它来获取实时片段【参考方案4】:

另一个简单的解决方案:

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

【讨论】:

这似乎非常适合我当前的片段需求。 如果您需要做的就是获取当前选定的 Fragment,这就是您所需要的 - 方法 setPrimaryItem 设置在附加上,并且在每次更新到 Fragment 的内部集时设置为当前项. 这听起来是个不错的解决方案,但setPrimaryItem() 被称为 after ViewPager.OnPageChangeListener#onPageSelected() 我不能使用它:-(【参考方案5】:

我知道这有几个答案,但也许这会对某人有所帮助。当我需要从我的ViewPager 获取Fragment 时,我使用了一个相对简单的解决方案。在您的ActivityFragment 持有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.
    

如果你知道你的FragmentViewPager中的位置,你可以直接打电话给getItem(knownPosition)

如果你不知道你的FragmentViewPager中的位置,你可以让你的孩子FragmentsgetUniqueId()这样的方法实现一个接口,并用它来区分他们.也可以循环遍历所有Fragments,查看类类型,如if(viewPagerFragment instanceof FragmentClassYouWant)

!!!编辑!!!

我发现getItem 只有在每个Fragment 需要第一次创建时才被FragmentPagerAdapter 调用,之后,Fragments 似乎被回收了使用FragmentManager。这样,FragmentPagerAdapter 的许多实现都会在 getItem 中创建 new Fragments。使用我上面的方法,这意味着我们将在每次调用getItem 时创建新的Fragments,因为我们遍历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
        
    

你将需要这个方法。

private static String makeFragmentName(int viewId, int position) 
    return "android:switcher:" + viewId + ":" + position;

【讨论】:

你只是findFragmentByTag(),但是我们可以在哪里设置带有片段的TAG?? @vince ViewPager 自己设置了这些标签。这个解决方案很脆弱,因为它依赖于知道ViewPager 的“隐藏”命名约定。 Streets of Boston 的答案是一个更全面的解决方案,我现在在我的项目中使用它(而不是这种方法)。 这很好用!但是我删除了“if (viewPagerFragment.isResumed())”条件,因为我需要更新不在屏幕上的 ListFragment 页面。然后当用户返回 ListFragment 页面时,它全部更新为新数据。【参考方案6】:

就我而言,上述解决方案均无效。

但是,由于我在片段中使用子片段管理器,因此使用了以下内容:

Fragment f = getChildFragmentManager().getFragments().get(viewPager.getCurrentItem());

这只有在管理器中的片段对应于 viewpager 项时才有效。

【讨论】:

这是在重新创建活动或片段时从视图寻呼机中获取旧片段的完美答案。【参考方案7】:

为了从 ViewPager 获取 当前可见片段。我正在使用这个简单的语句,它运行良好。

      public Fragment getFragmentFromViewpager()  
      
         return ((Fragment) (mAdapter.instantiateItem(mViewPager, mViewPager.getCurrentItem())));
      

【讨论】:

【参考方案8】:

我首先列出了我将要使用的所有片段 (List&lt;Fragment&gt; fragments;),然后将它们添加到寻呼机,以便更轻松地处理当前查看的片段。

所以:

@Override
onCreate()
    //initialise the list of fragments
    fragments = new Vector<Fragment>();

    //fill up the list with out fragments
    fragments.add(Fragment.instantiate(this, MainFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, MenuFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, StoresFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, AboutFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, ContactFragment.class.getName()));


    //Set up the pager
    pager = (ViewPager)findViewById(R.id.pager);
    pager.setAdapter(new MyFragmentPagerAdapter(getSupportFragmentManager(), fragments));
    pager.setOffscreenPageLimit(4);

所以可以这样调用:

public Fragment getFragment(ViewPager pager)   
    Fragment theFragment = fragments.get(pager.getCurrentItem());
    return theFragment;

所以我可以把它放在一个 if 语句中,如果它在正确的片段上才会运行

Fragment tempFragment = getFragment();
if(tempFragment == MyFragmentNo2.class)
    MyFragmentNo2 theFrag = (MyFragmentNo2) tempFragment;
    //then you can do whatever with the fragment
    theFrag.costomFunction();

但这只是我的 hack 和 slash 方法,但它对我有用,我使用它确实会在按下后退按钮时对我当前显示的片段进行相关更改。

【讨论】:

对我来说最好的答案【参考方案9】:

这是基于上面 Steven 的回答。这将返回已附加到父活动的片段的实际实例。

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
    for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) 

        Fragment viewPagerFragment = (Fragment) mViewPager.getAdapter().instantiateItem(mViewPager, i);
        if(viewPagerFragment != null && viewPagerFragment.isAdded()) 

            if (viewPagerFragment instanceof FragmentOne)
                FragmentOne oneFragment = (FragmentOne) viewPagerFragment;
                if (oneFragment != null)
                    oneFragment.update(); // your custom method
                
             else if (viewPagerFragment instanceof FragmentTwo)
                FragmentTwo twoFragment = (FragmentTwo) viewPagerFragment;

                if (twoFragment != null)
                    twoFragment.update(); // your custom method
                
            
        
    

【讨论】:

【参考方案10】:

我找不到一种简单、干净的方法来做到这一点。但是, ViewPager 小部件只是另一个 ViewGroup ,它托管您的片段。 ViewPager 将这些片段作为直接子级。因此,您可以迭代它们(使用 .getChildCount() 和 .getChildAt() ),并查看您正在寻找的片段实例当前是否已加载到 ViewPager 并获取对它的引用。例如。您可以使用一些静态唯一 ID 字段来区分片段。

请注意,ViewPager 可能没有加载您要查找的片段,因为它是一个类似于 ListView 的虚拟化容器。

【讨论】:

感谢您的回答,我用 adpter.getItem();我是Android编程的大一新生。非常感谢你。现在我可以检索 ListFragment 并且我想将 footerView 添加到它,虽然我在我的 Activity 中执行此操作,然后 logcat 打印:“java.lang.IllegalStateException: Content view not yet. created”。我知道为什么但我很难处理用它。 FragmentActivity 有 onAttachFragment() 方法,对 ViewPager 的片段内容执行这项工作吗?【参考方案11】:

FragmentPagerAdapter 是片段的工厂。如果仍在内存中,要根据其位置查找片段,请使用:

public Fragment findFragmentByPosition(int position) 
    FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter();
    return getSupportFragmentManager().findFragmentByTag(
            "android:switcher:" + getViewPager().getId() + ":"
                    + fragmentPagerAdapter.getItemId(position));

v4 支持 api 的示例代码。

【讨论】:

它在 onresume() 中返回 null。知道为什么和锄头来解决它吗?【参考方案12】:

不需要在后期需要调用getItem() 或其他方法来获取托管在ViewPager 中的Fragment 的引用。如果您想更新Fragment 内部的一些数据,请使用这种方法:Update ViewPager dynamically?

关键是在Adaper 中设置新数据并调用notifyDataSetChanged(),后者又会调用getItemPosition(),将Fragment 的引用传递给您,并让您有机会更新它。所有其他方式都需要您参考自己或其他一些不是好的解决方案。

@Override
public int getItemPosition(Object object) 
    if (object instanceof UpdateableFragment) 
        ((UpdateableFragment) object).update(xyzData);
    
    //don't return POSITION_NONE, avoid fragment recreation. 
    return super.getItemPosition(object);

【讨论】:

这里没看懂,你需要一个Fragment的引用才能使用getItemPosition(),所以你还不如不使用getItemPosition吧? getItemPosition() 是适配器中的一个方法。你不会直接调用它。你有你的适配器的引用,所以你调用adapter.notifyDataSetChanged(),然后通过传递你的Fragments 的引用调用你的适配器的getItemPosition()。你可以在这里看到一个完整的实现***.com/questions/19891828/… 我已经阅读了一遍,但我仍然不明白。您仍然需要直接引用这些片段才能对它们进行调用,对吗?您提到这是一种黑客行为,但我没有看到其他选择; adapter.getItem(i) 显然是行不通的。 好的,我已经更新了我的答案以澄清更多信息。当然,更新Fragment 需要参考,但如何获得参考是有争议的。其他解决方案使用类似于"android:switcher:"+id 的字符串从FragmentManager 获取引用,或者从getItemosition() 返回POSITION_NONE,导致所有片段重新创建自己。 谢谢,这更有意义并且符合我的经验(所以我可能没有做错什么,哈)。【参考方案13】:

必须将 FragmentPagerAdapter 扩展至您的 ViewPager 适配器类。 如果您使用FragmentStatePagerAdapter,那么您将无法通过其ID 找到您的Fragment

public static String makeFragmentName(int viewPagerId, int index) 
  return "android:switcher:" + viewPagerId + ":" + index;

如何使用这个方法:-

Fragment mFragment = ((FragmentActivity) getContext()).getSupportFragmentManager().findFragmentByTag(
       AppMethodUtils.makeFragmentName(mViewPager.getId(), i)
);
InterestViewFragment newFragment = (InterestViewFragment) mFragment;

【讨论】:

【参考方案14】:

嘿,我已经回答了这个问题here。基本上,你需要覆盖

public Object instantiateItem(ViewGroup container, int position)

FragmentStatePagerAdapter 的方法。

【讨论】:

【参考方案15】:

最好的解决方案是使用我们在CodePath 创建的名为SmartFragmentStatePagerAdapter 的扩展。遵循该指南,这使得从 ViewPager 中检索片段和当前选择的片段变得更加容易。它还可以更好地管理嵌入在适配器中的片段的内存。

【讨论】:

【参考方案16】:

最简单最简洁的方式。如果您在ViewPager 中的所有片段都属于不同的类,您可以按如下方式检索和区分它们:

public class MyActivity extends Activity


    @Override
    public void onAttachFragment(Fragment fragment) 
        super.onAttachFragment(fragment);
        if (fragment.getClass() == MyFragment.class) 
            mMyFragment = (MyFragment) fragment;
        
    


【讨论】:

这也是错误的,因为当您使用 ViewPager 时会附加多个片段。有当前页面片段,左边一个,右边一个。这允许用户在它们之间滑动,而不必仅在用户到达它们时对其进行初始化。【参考方案17】:

我用一些不同的方法轻松实现了这一点。

我的自定义 FragmentAdapter.getItem 方法返回的不是 new MyFragment(),而是在 FragmentAdapter 构造函数中创建的 MyFragment 实例。

然后在我的活动中,我从适配器获取片段,检查它是否是 instanceOf 需要的片段,然后强制转换并使用所需的方法。

【讨论】:

【参考方案18】:

在 /values/integers.xml 中创建整数资源 id

<integer name="page1">1</integer>
<integer name="page2">2</integer>
<integer name="page3">3</integer>

然后在PagerAdapter的getItem函数中:

public Fragment getItem(int position) 

        Fragment fragment = null;

        if (position == 0) 
            fragment = FragmentOne.newInstance();
            mViewPager.setTag(R.integer.page1,fragment);

        
        else if (position == 1) 

            fragment = FragmentTwo.newInstance();
            mViewPager.setTag(R.integer.page2,fragment);

         else if (position == 2) 

            fragment = FragmentThree.newInstance();
            mViewPager.setTag(R.integer.page3,fragment);

        

        return fragment;
        

然后在activity中编写这个函数来获取片段引用:

private Fragment getFragmentByPosition(int position) 
    Fragment fragment = null;

    switch (position) 
        case 0:
            fragment = (Fragment) mViewPager.getTag(R.integer.page1);
            break;

        case 1:

            fragment = (Fragment) mViewPager.getTag(R.integer.page2);
            break;

        case 2:
            fragment = (Fragment) mViewPager.getTag(R.integer.page3);
            break;
            

            return fragment;
    

通过调用上述函数获取片段引用,然后将其转换为您的自定义片段:

Fragment fragment = getFragmentByPosition(position);

        if (fragment != null) 
                    FragmentOne fragmentOne = (FragmentOne) fragment;
                    

【讨论】:

【参考方案19】:

在片段管理器中迭代片段的简单方法。找到 viewpager,它有部分位置参数,放在 public static PlaceholderFragment newInstance(int sectionNumber)

public PlaceholderFragment getFragmentByPosition(Integer pos)
    for(Fragment f:getChildFragmentManager().getFragments())
        if(f.getId()==R.id.viewpager && f.getArguments().getInt("SECTNUM") - 1 == pos) 
            return (PlaceholderFragment) f;
        
    
    return null;

【讨论】:

【参考方案20】:

在片段中

public int getArgument()
   return mPage;

public void update()


在 FragmentActivity 中

List<Fragment> fragments = getSupportFragmentManager().getFragments();
for(Fragment f:fragments)
    if((f instanceof PageFragment)&&(!f.isDetached()))
          PageFragment pf = (PageFragment)f;   
          if(pf.getArgument()==pager.getCurrentItem())pf.update();
    

【讨论】:

【参考方案21】:

在 TabLayout 中有多个用于 Fragment 的选项卡。您可以使用片段的索引通过 Tag 找到片段。

例如。 Fragment1 的索引为 0,所以在findFragmentByTag() 方法中,为 Viewpager 传递标签。使用 fragmentTransaction 后,您可以添加,替换片段。

String tag = "android:switcher:" + R.id.viewPager + ":" + 0; Fragment1 f = (Fragment1) getSupportFragmentManager().findFragmentByTag(tag);

【讨论】:

【参考方案22】:

好的适配器FragmentStatePagerAdapter我资助了一个解决方案:

在您的 FragmentActivity 中:

ActionBar mActionBar = getSupportActionBar(); 
mActionBar.addTab(mActionBar.newTab().setText("TAB1").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment1.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB2").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment2.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB3").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment3.class.getName())));

viewPager = (STViewPager) super.findViewById(R.id.viewpager);
mPagerAdapter = new MyPagerAdapter(getSupportFragmentManager(), mActionBar);
viewPager.setAdapter(this.mPagerAdapter);

并在您的 FragmentActivity 类中创建一个方法 - 这样该方法就可以让您访问您的 Fragment,您只需为其指定您想要的 Fragment 的位置:

public Fragment getActiveFragment(int position) 
String name = MyPagerAdapter.makeFragmentName(position);
return getSupportFragmentManager().findFragmentByTag(name);

在您的适配器中:

public class MyPagerAdapter extends FragmentStatePagerAdapter 

private final ActionBar actionBar;
private final FragmentManager fragmentManager;

public MyPagerAdapter(FragmentManager fragmentManager, com.actionbarsherlock.app.ActionBarActionBar mActionBar) super(fragmentManager);
this.actionBar = mActionBar;
this.fragmentManager = fragmentManager;


@Override
public Fragment getItem(int position) 
getSupportFragmentManager().beginTransaction().add(mTchatDetailsFragment, makeFragmentName(position)).commit();
return (Fragment)this.actionBar.getTabAt(position);


@Override
public int getCount() 
return this.actionBar.getTabCount();


@Override
public CharSequence getPageTitle(int position) 
return this.actionBar.getTabAt(position).getText();


private static String makeFragmentName(int viewId, int index) 
return "android:fragment:" + index;



【讨论】:

【参考方案23】:
Fragment yourFragment = yourviewpageradapter.getItem(int index);

index 是适配器中片段的位置,就像您首先添加 fragment1 所以检索 fragment1 传递 index 为 0 等等休息

【讨论】:

以上是关于从 ViewPager 中检索片段的主要内容,如果未能解决你的问题,请参考以下文章

从 Viewpager2 片段访问父片段函数

onActivityResult 不会从 viewPager 片段调用

Android:将“ViewPager”动画从片段更改为片段

如何将值从其他活动传递给 viewpager 片段?

从Activity设置子片段的ViewPager页面

从ViewPager android替换片段