Можно ли получить доступ к текущему фрагменту, просматриваемому ViewPager?
у меня есть приложение с ViewPager и три Fragment s. Я пытаюсь выяснить, как получить текущий Fragment просматривается, чтобы я мог добраться до его аргументов.
у меня есть OnPageChangeListener захват текущего индекса страницы, но
ViewPager.getChildAt(int position);
возвращает a View. Какая связь между этим View и в течение Fragment?
11 ответов:
Я, наконец, нашел ответ это сработало для меня. В принципе, вы можете получить доступ к фрагменту на странице viewPager с помощью тега "телефоны:коммутатор:"+ИД Р..viewpager+":0".
я решил эту проблему иначе. Вместо того, чтобы искать фрагмент из действия, я регистрирую фрагмент во время его метода 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); } }
Edit-не делайте этого. Если у вас есть соблазн, прочитайте комментарии, почему это плохая идея.
по нечетной случайности вы все еще пытаетесь решить эту проблему:
расширения
FragmentPagerAdapter. В конструкторе создайте необходимые фрагменты и сохраните их в списке (массив/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]; }Я не уверен, что это общепринятый способ сделать это, но это сработало для меня.
Edit
Это действительно не хороший способ пойти. Если вы планируете обрабатывать изменения ориентации или ваше приложение переходит в фоновый режим, то это, вероятно, нарушит ваш код. Пожалуйста, прочитайте комментарии ниже этого ответа для получения дополнительной информации. Вместо использования @Джеймс 'ы ответ
Да, это возможно, если вы используете
FragmentStatePagerAdapter.ViewPager vp; //... YourFragment fragment = (YourFragment) adapter.instantiateItem(vp, vp.getCurrentItem());
ПОЖАЛУЙСТА, НЕ ИСПОЛЬЗУЙТЕ ЭТО
сделайте ваш адаптер расширить следующее
FragmentStatePagerWithCurrentAdapterкласс и вместо реализацииgetItemвыполнить тот же код вgetItemAtIndexустановить
ViewPagerOnPageChangeListener, к экземпляру адаптер.когда вам нужно получить доступ к текущему фрагменту, вы просто вызываете
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 вы должны вернуть представление, чтобы нарисовать пользовательский интерфейс для вашего фрагмента, я думаю, что это отношение.
также этот вопрос может быть похож: получить сфокусированный вид из 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, если существует:
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(); }
Хорхе Гарсиа FragmentStatePagerWithCurrentAdapter Это очень хорошее решение, но оно нуждается в незначительном улучшении. В случае, если действие будет уничтожено и повторно создано в ответ на изменение конфигурации или что-то подобное, getItem не будет вызываться для фрагментов, которые были сохранены и получены диспетчером фрагментов. Поэтому я переопределяю 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());можно получить текущую страницу фрагмента дисплея.
Comments