是否有可能访问ViewPager正在查看的当前片段?
我有一个ViewPager
和三个Fragment
的应用程序。 我试图弄清楚如何让当前Fragment
被观看,这样我就可以得到它的论点。
我有一个OnPageChangeListener
抓取当前页面的索引,但是
ViewPager.getChildAt(int position);
返回一个View
。 这个View
和现在的Fragment
之间有什么关系?
我终于find了一个适合我的答案 。 基本上,您可以使用标签“android:switcher:”+ R.id.viewpager +“:0”来访问viewPager页面的片段。
我反过来解决了这个问题。 我不是从活动中search片段,而是在它的onAttach()方法中注册片段,并在onStop()方法中取消注册。 基本思路:
分段:
@Override public void onAttach(Activity activity) { super.onAttach(activity); try{ mActivity = (IMyActivity)activity; }catch(ClassCastException e){ throw new ClassCastException(activity.toString() +" must be a IMyActivity"); } mActivity.addFragment(this); } @Override public void onStop() { mActivity.removeFragment(this); super.onStop(); }
IMyActivity:
public interface IFriendActivity { public void addFragment(Fragment f); public void removeFragment(Fragment f); }
MyActivity:
public class MyActivity implements IMyActivity{ [...] @Override public void addFragment(Fragment f) { mFragments.add(f); } @Override public void removeFragment(Fragment f) { mFragments.remove(f); } }
编辑 – 不要这样做。 如果你有兴趣,请阅读评论为什么这是一个坏主意。
在奇怪的机会,你仍然试图解决这个问题:
扩展FragmentPagerAdapter
。 在构造函数中,构build您需要的碎片并将它们存储在碎片的List(array / ArrayList)中。
private final int numItems = 3; Fragment[] frags; public SwipeAdapter (FragmentManager fm) { super(fm); //Instantiate the Fragments frags = new Fragment[numItems]; Bundle args = new Bundle(); args.putString("arg1", "foo"); frags[0] = new MyFragment(); frags[1] = new YourFragment(); frags[2] = new OurFragment(); frags[2].setArguments(args); }
那么对于getItem(int position)
,你可以做类似的事情
public Fragment getItem(int position) { return frags[position]; }
我不确定这是否是普遍接受的方式,但它对我有效。
编辑
这真的不是一个好的方法。 如果您打算处理方向更改或您的应用程序进入后台,那么这可能会破坏您的代码。 请阅读下面的评论以获取更多信息。 而是用@詹姆斯的答案
是的,如果您使用FragmentStatePagerAdapter
,则可以。
ViewPager vp; //... YourFragment fragment = (YourFragment) adapter.instantiateItem(vp, vp.getCurrentItem());
请不要使用这个
使您的适配器扩展以下FragmentStatePagerWithCurrentAdapter
类,而不是实现getItem
实现相同的代码到getItemAtIndex
将ViewPager
OnPageChangeListener
设置为适配器的实例。
当你需要访问当前的Fragment时,你只需调用adapter.getCurrentItem()
。
package your.package; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.SparseArray; import android.view.ViewGroup; public abstract class FragmentStatePagerWithCurrentAdapter extends FragmentStatePagerAdapter implements OnPageChangeListener { int currentPage = 0; private SparseArray<Fragment> mPageReferenceMap = new SparseArray<Fragment>(); public FragmentStatePagerWithCurrentAdapter(FragmentManager fm) { super(fm); } @Override public final Fragment getItem(int index) { Fragment myFragment = getItemAtIndex(index); mPageReferenceMap.put(index, myFragment); return myFragment; } public abstract Fragment getItemAtIndex(int index); @Override public void destroyItem(ViewGroup container, int position, Object object) { super.destroyItem(container, position, object); mPageReferenceMap.remove(Integer.valueOf(position)); } public Fragment getCurrentItem() { return mPageReferenceMap.get(currentPage); } @Override public void onPageScrollStateChanged(int arg0) { } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageSelected(int newPageIndex) { currentPage = newPageIndex; } }
我用作参考以下博客文章: http : //tamsler.blogspot.com/2011/11/android-viewpager-and-fragments-part-ii.html
这里已经解释了: http : //developer.android.com/guide/topics/fundamentals/fragments.html
在OnCreateView你必须返回一个视图来绘制你的片段的UI,我认为这是关系。
此外,这个问题可能是类似的: 从ViewPager获得专注的视图
您可以这样做: – 在视图寻呼机适配器(如PagerAdapter,FragmentStatePagerAdapter …)的类范围覆盖方法instantiateItem:
@Override public Object instantiateItem(ViewGroup container, int position) { final Fragment frag = (Fragment) super.instantiateItem(container, position); if(frag instanceof ListNoteOfTypeFragment){ final ListNoteOfTypeFragment listNoteOfTypeFragment = (ListNoteOfTypeFragment) frag; //do whatever you want with your fragment here listNoteOfTypeFragment.setNoteChangeListener(mListener); } return frag; }
确切的答案,无缝工作(但小破解):
页面片段布局中的某处:
<FrameLayout android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone" android:id="@+id/fragment_reference"> <View android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone"/> </FrameLayout>
在片段的onCreateView()中:
... View root = inflater.inflate(R.layout.fragment_page, container, false); ViewGroup ref = (ViewGroup)root.findViewById(R.id.fragment_reference); ref.setTag(this); ref.getChildAt(0).setTag("fragment:" + pageIndex); return root;
以及从ViewPager返回Fragment的方法(如果存在):
public Fragment getFragment(int pageIndex) { View w = mViewPager.findViewWithTag("fragment:" + pageIndex); if (w == null) return null; View r = (View) w.getParent(); return (Fragment) r.getTag(); }
Jorge Garcia的FragmentStatePagerWithCurrentAdapter是一个非常好的解决scheme,但是需要稍微改进。 如果活动被破坏并重新创build,以响应configuration更改或类似的事情,getItem将不会被片段pipe理器保存和检索的片段调用。 所以我重写getItem通常在我的子类,我把下面的FragmentStatePagerWithCurrentAdapter
@Override public Object instantiateItem(ViewGroup container, int position) { Object item = super.instantiateItem(container, position); if ( item instanceof Fragment ) { pageReferenceMap.put(position, (Fragment)item); } return item; }
每当访问该位置的片段时,都会调用instantiateItem。
或者把所有碎片保存在地图中:
public class MyFragment extends Fragment implements OnPageChangeListener { private ViewPager viewPager; private FragmentStatePagerAdapter viewAdapter; private View rootView; private Map<Integer, Fragment> fragments = new HashMap<Integer, Fragment>(); @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.introdution, container, false); viewPager = (ViewPager) rootView.findViewById(R.id.pager); viewAdapter = new ViewAdapter(getFragmentManager()); viewPager.setAdapter(viewAdapter); viewPager.addOnPageChangeListener(this); return rootView; } private class ViewAdapter extends FragmentStatePagerAdapter { public ViewAdapter(FragmentManager fragmentManager) { super(fragmentManager); } @Override public Fragment getItem(int position) { Fragment result = null; switch (position) { case 0: result = Fragment1.newInstance(); break; case 1: result = Fragment2.newInstance(); break; } if (result != null) fragments.put(position, result); return result; } @Override public int getCount() { return 2; } } @Override public void onPageScrollStateChanged(int arg0) { } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageSelected(int position) { Fragment currentFragment = fragments.get(position); } }
我认为有更好的方法来使用这个
Log.i(TAG, "getCurrentItem " + mViewPager.getCurrentItem());
可以得到当前的显示片段页面。