在viewpager中获取当前的Fragment实例

下面是我的代码,它有3 Fragment classes每个embeddedViewPager的3个选项卡。 我有一个菜单选项。 如onOptionsItemSelected() ,通过select一个选项,我需要更新当前可见的片段。 要更新我必须调用片段类中的方法。 有人可以build议如何调用该方法吗?

 public class MainActivity extends ActionBarActivity { ViewPager ViewPager; TabsAdapter TabsAdapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ViewPager = new ViewPager(this); ViewPager.setId(R.id.pager); setContentView(ViewPager); final ActionBar bar = getSupportActionBar(); bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); //Attaching the Tabs to the fragment classes and setting the tab title. TabsAdapter = new TabsAdapter(this, ViewPager); TabsAdapter.addTab(bar.newTab().setText("FragmentClass1"), FragmentClass1.class, null); TabsAdapter.addTab(bar.newTab().setText("FragmentClass2"), FragmentClass2.class, null); TabsAdapter.addTab(bar.newTab().setText("FragmentClass3"), FragmentClass3.class, null); if (savedInstanceState != null) { bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0)); } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.addText: **// Here I need to call the method which exists in the currently visible Fragment class** return true; } return super.onOptionsItemSelected(item); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt("tab", getSupportActionBar().getSelectedNavigationIndex()); } public static class TabsAdapter extends FragmentPagerAdapter implements ActionBar.TabListener, ViewPager.OnPageChangeListener { private final Context mContext; private final ActionBar mActionBar; private final ViewPager mViewPager; private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>(); static final class TabInfo { private final Class<?> clss; private final Bundle args; TabInfo(Class<?> _class, Bundle _args) { clss = _class; args = _args; } } public TabsAdapter(ActionBarActivity activity, ViewPager pager) { super(activity.getSupportFragmentManager()); mContext = activity; mActionBar = activity.getSupportActionBar(); mViewPager = pager; mViewPager.setAdapter(this); mViewPager.setOnPageChangeListener(this); } public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) { TabInfo info = new TabInfo(clss, args); tab.setTag(info); tab.setTabListener(this); mTabs.add(info); mActionBar.addTab(tab); notifyDataSetChanged(); } @Override public void onPageScrollStateChanged(int state) { // TODO Auto-generated method stub } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { // TODO Auto-generated method stub } @Override public void onPageSelected(int position) { // TODO Auto-generated method stub mActionBar.setSelectedNavigationItem(position); } @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { // TODO Auto-generated method stub } @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { Object tag = tab.getTag(); for (int i=0; i<mTabs.size(); i++) { if (mTabs.get(i) == tag) { mViewPager.setCurrentItem(i); } } tabPosition = tab.getPosition(); } @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { // TODO Auto-generated method stub } @Override public Fragment getItem(int position) { TabInfo info = mTabs.get(position); return Fragment.instantiate(mContext, info.clss.getName(), info.args); } @Override public int getCount() { return mTabs.size(); } } } 

假设下面是我想要调用的方法updateList()的片段类:

  public class FragmentClass1{ ArrayList<String> originalData; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View fragmentView = inflater.inflate(R.layout.frag1, container, false); originalData = getOriginalDataFromDB(); return fragmentView; } public void updateList(String text) { originalData.add(text); //Here I could do other UI part that need to added } } 

通过select一个选项,我需要更新当前可见的片段。

一个简单的方法是使用与FragmentPagerAdapter实现相关的技巧:

 case R.id.addText: Fragment page = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + ViewPager.getCurrentItem()); // based on the current position you can then cast the page to the correct // class and call the method: if (ViewPager.getCurrentItem() == 0 && page != null) { ((FragmentClass1)page).updateList("new item"); } return true; 

请重新考虑你的variables命名约定,使用作为variables名称的类的名称是非常混乱(所以没有ViewPager ViewPager ,例如使用ViewPager mPager )。

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

首先跟踪所有“活动”片段页面。 在这种情况下,您将跟踪由ViewPager使用的FragmentStatePagerAdapter中的片段页面。

 @Override public Fragment getItem(int index) { Fragment myFragment = MyFragment.newInstance(); mPageReferenceMap.put(index, myFragment); return myFragment; } 

为了避免引用“非活动”片段页面,您需要实现FragmentStatePagerAdapter的destroyItem(…)方法:

 @Override public void destroyItem (ViewGroup 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); } 

希望它可以帮助!

这是我不能得到NullPointerExceptionexception的特定片段类的实例variables。 这可能对其他坚持相同事情的人有帮助。 在onOptionsItemSelected()中,我编码如下:

 if(viewPager.getCurrentItem() == 0) { FragmentClass1 frag1 = (FragmentClass1)viewPager.getAdapter().instantiateItem(viewPager, viewPager.getCurrentItem()); frag1.updateList(text); }else if(viewPager.getCurrentItem() == 1) { FragmentClass2 frag2 = (FragRecentApps)viewPager.getAdapter().instantiateItem(viewPager, viewPager.getCurrentItem()); frag2.updateList(text); } 

FragmentStatePagerAdapter具有名称为instantiateItem的public方法,该方法根据指定的参数值返回您的framgment,此方法具有两个参数ViewGroup(ViewPager)和position。

 public Object instantiateItem(ViewGroup container, int position); 

用这个方法得到指定位置的片段,

 Fragment fragment = (Fragment) adaper.instantiateItem(mViewPager, position); 

这段代码对我有帮助,请检查一下。

这里有很多答案,并没有真正解决这样一个基本事实:确实没有办法做到这一点,并且不会导致你在将来的某个时候在脚下射击。

FragmentStatePagerAdapter是唯一知道如何可靠地访问由FragmentManager跟踪的FragmentManager – 任何试图尝试和猜测片段的id或标记的尝试都是不可靠的,长期的。 当状态被保存/恢复时,尝试手动跟踪这些实例可能不会很好,因为FragmentStatePagerAdapter在恢复状态时可能不会调用callback。

关于我唯一能做的工作就是复制FragmentStatePagerAdapter的代码,并添加一个返回片段的方法( mFragments.get(pos) )。 请注意,此方法假定片段实际上是可用的(即在某个点上可见)。

如果你特别喜欢冒险,你可以使用reflection来访问私有mFragments列表的元素,但是我们又回到了mFragments列表的名字不保证保持不变)。

当前片段:

 Fragment f = mSectionsPagerAdapter.getItem(mViewPager.getCurrentItem()); 

请注意,这适用于默认的选项卡式活动模板实现。

我已经使用了以下内容:

  int index = vpPager.getCurrentItem(); MyPagerAdapter adapter = ((MyPagerAdapter)vpPager.getAdapter()); MyFragment suraVersesFragment = (MyFragment)adapter.getRegisteredFragment(index); 

通过select一个选项,我需要更新当前可见的片段。

要获取对当前可见片段的引用,假定您有对ViewPager的引用作为mPager 。 然后下面的步骤将得到currentFragment的引用:

  1. PageAdapter adapter = mPager.getAdapter();
  2. int fragmentIndex = mPager.getCurrentItem();
  3. FragmentStatePagerAdapter fspa = (FragmentStatePagerAdapter)adapter;
  4. Fragment currentFragment = fspa.getItem(fragmentIndex);

第三行使用的唯一一个通常是有效的。 FragmentStatePagerAdapter是ViewPager的一个有用的适配器。

我知道它太晚了,但我有非常简单的方法来做到这一点,

//在0位置的片段

 ((mFragment) viewPager.getAdapter().instantiateItem(viewPager, 0)).yourMethod(); 

我有同样的问题,并使用此代码解决它。

 MyFragment fragment = (MyFragment) thisActivity.getFragmentManager().findFragmentById(R.id.container); 

只需用您的片段的名称replace名称MyFragment,并添加您的片段容器的ID。

这比接受的答案更具前瞻性:

 public class MyFragmentPagerAdapter extends FragmentPagerAdapter { /* ------------------------------------------------------------------------------------------ */ // region Private attributes : private Context _context; private FragmentManager _fragmentManager; private Map<Integer, String> _fragmentsTags = new HashMap<>(); // endregion /* ------------------------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------------------------ */ // region Constructor : public MyFragmentPagerAdapter(Context context, FragmentManager fragmentManager) { super(fragmentManager); _context = context; _fragmentManager = fragmentManager; } // endregion /* ------------------------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------------------------ */ // region FragmentPagerAdapter methods : @Override public int getCount() { return 2; } @Override public Fragment getItem(int position) { if(_fragmentsTags.containsKey(position)) { return _fragmentManager.findFragmentByTag(_fragmentsTags.get(position)); } else { switch (position) { case 0 : { return Fragment.instantiate(_context, Tab1Fragment.class.getName()); } case 1 : { return Fragment.instantiate(_context, Tab2Fragment.class.getName()); } } } return null; } @Override public Object instantiateItem(ViewGroup container, int position) { // Instantiate the fragment and get its tag : Fragment result = (Fragment) super.instantiateItem(container, position); _fragmentsTags.put(position, result.getTag()); return result; } // endregion /* ------------------------------------------------------------------------------------------ */ } 

每个Fragment添加自己的菜单项并直接处理onOptionsItemSelected(),就可以更好地解决上述情况,如官方文档中所述 。 最好避免无证的技巧。

FragmentStatePagerAdapter有一个名为mCurrentPrimaryItemtypes为Fragment的私有实例variables。 人们只能想知道为什么Android开发者没有提供一个getter。 这个variables在setPrimaryItem()方法中被实例化。 所以,用这种方法重写这个方法,以获得对这个variables的引用。 我只是简单地声明了自己的mCurrentPrimaryItem并将setPrimaryItem()的内容复制到了我的覆盖中。

在你的FragmentStatePagerAdapter的实现中:

 private Fragment mCurrentPrimaryItem = null; @Override public void setPrimaryItem(ViewGroup container, int position, Object object) { Fragment fragment = (Fragment)object; if (fragment != mCurrentPrimaryItem) { if (mCurrentPrimaryItem != null) { mCurrentPrimaryItem.setMenuVisibility(false); mCurrentPrimaryItem.setUserVisibleHint(false); } if (fragment != null) { fragment.setMenuVisibility(true); fragment.setUserVisibleHint(true); } mCurrentPrimaryItem = fragment; } } public TasksListFragment getCurrentFragment() { return (YourFragment) mCurrentPrimaryItem; } 

在我的活动中,我有:

 int currentPage = 0;//start at the first tab private SparseArray<Fragment> fragments;//list off fragments viewPager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int pos) { currentPage = pos;//update current page } @Override public void onPageScrolled(int arg0, float arg1, int arg2) {} @Override public void onPageScrollStateChanged(int arg0) {} }); @Override public void onAttachFragment(Fragment fragment) { super.onAttachFragment(fragment); if(fragment instanceof Fragment1) fragments.put(0, fragment); if(fragment instanceof Fragment2) fragments.put(2, fragment); if(fragment instanceof Fragment3) fragments.put(3, fragment); if(fragment instanceof Fragment4) fragments.put(4, fragment); } Then I have the following method for getting the current fragment public Fragment getCurrentFragment() { return fragments.get(currentPage); } 
 final ViewPager.OnPageChangeListener onPageChangeListener = new ViewPager.OnPageChangeListener() { @Override public void onPageSelected(int position) { switch (position) { case 0: FragmentClass1 frag1 = (FragmentClass1) viewPager.getAdapter() .instantiateItem(viewPager, viewPager.getCurrentItem()); frag1.updateList("Custom text"); break; case 1: break; case 2: break; } } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageScrollStateChanged(int state) { } }; viewPager.addOnPageChangeListener(onPageChangeListener); viewPager.setAdapter(adapter); viewPager.post(new Runnable() { @Override public void run() { onPageChangeListener.onPageSelected(viewPager.getCurrentItem()); } }); 

有时候这个片段可能派发一个空对象,所以你可以运行一个新的Runnable来解决这个问题。

谢谢瑞克

覆盖FragmentPagerAdapter中的setPrimaryItem:该对象是可见的片段:

  @Override public void setPrimaryItem(ViewGroup container, int position, Object object) { if (mCurrentFragment != object) { mCurrentFragment = (LeggiCapitoloFragment) object; } super.setPrimaryItem(container, position, object); } 

阅读所有评论和答案后,我将解释这个问题的最佳解决scheme。 最好的select是@ rik的解决scheme,所以我的改进是基于他的。

而不必像每个FragmentClass一样询问

 if(FragmentClass1){ ... if(FragmentClass2){ ... } 

创build你自己的界面,并制造你的孩子的碎片来实现它,像

 public interface MyChildFragment { void updateView(int position); } 

然后,你可以做这样的事情来启动和更新你的内部片段。

 Fragment childFragment = (Fragment) mViewPagerDetailsAdapter.instantiateItem(mViewPager,mViewPager.getCurrentItem()); if (childFragment != null) { ((MyChildFragment) childFragment).updateView(); } 

PS请注意放置代码的位置,如果在系统实际创build之前调用insatiateItem,则您的子片段的savedInstanceState将为空

 public void onCreate(@Nullable Bundle savedInstanceState){ super(savedInstanceState) } 

会崩溃你的应用程序。

祝你好运

只需从寻呼机获取当前的项目,然后询问您的适配器到该位置的片段。

  int currentItem = viewPager.getCurrentItem(); Fragment item = mPagerAdapter.getItem(currentItem); if (null != item && item.isVisible()) { //do whatever want to do with fragment after doing type checking return; } 

获取当前片段 – 在ViewPager中获取位置public void onPageSelected(final int position) ,然后

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

SECTNUM – 在公共静态PlaceholderFragment中分配的位置参数newInstance(int sectionNumber); 的片段

getChildFragmentManager()或getFragmentManager() – 取决于SectionsPagerAdapter的创build方式