Как добавить фрагмент внутри ViewPager с помощью Nested Fragment (Android 4.2)

У меня есть ViewPager с тремя Fragments , каждый из которых показывает List (или Grid ).

На новом Android API level 17 (Jelly Bean 4.2) одной из функций является Nested Fragments . Новое описание функциональности гласит:

Если вы используете ViewPager для создания фрагментов, которые прокручиваются влево и вправо и потребляют большую часть пространства экрана, теперь вы можете вставлять фрагменты на каждую страницу фрагмента.

Поэтому, если я правильно понимаю, теперь я могу создать ViewPager с Fragments (например, внутри внутри внутри), а когда пользователь нажимает кнопку, показывает другой Fragment не ViewPager используя эту новую функцию.

Я потратил свое утро, пытаясь реализовать это несколько разных способов, но я не могу заставить его работать … Может ли кто-нибудь добавить простой пример того, как это реализовать?

PS: Меня это интересует только с помощью getChildFragmentManager чтобы узнать, как это работает.

Solutions Collecting From Web of "Как добавить фрагмент внутри ViewPager с помощью Nested Fragment (Android 4.2)"

Предполагая, что вы создали правильные макеты xml. Теперь очень просто отобразить фрагменты в ViewPager, который размещен другим фрагментом.

Код выглядит примерно так в родительском фрагменте:

  @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_parent, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ViewPager mViewPager = (ViewPager) view.findViewById(R.id.viewPager); mViewPager.setAdapter(new MyAdapter(getChildFragmentManager())); } public static class MyAdapter extends FragmentPagerAdapter { public MyAdapter(FragmentManager fm) { super(fm); } @Override public int getCount() { return 4; } @Override public Fragment getItem(int position) { Bundle args = new Bundle(); args.putInt(TextViewFragment.POSITION_KEY, position); return TextViewFragment.newInstance(args); } } 

При создании экземпляра FragmentPagerAdapter важно использовать Fragment.getChildFragmentManager () . Также обратите внимание, что вы не можете использовать Fragment.setRetainInstance () для фрагментов детей, иначе вы получите исключение.

Исходный код можно найти по адресу: https://github.com/marcoRS/nested-fragments

Изменить: если вы хотите заменить все содержимое страницы в ViewPager вы все равно можете использовать вложенные фрагменты, но необходимы некоторые изменения. Проверьте пример ниже ( FragmentActivity , настройка ViewPager и PagerAdapter совпадает с предыдущим фрагментом кода):

 // this will act as a fragment container, representing one page in the ViewPager public static class WrapperFragment extends Fragment implements ReplaceListener { public static WrapperFragment newInstance(int position) { WrapperFragment wp = new WrapperFragment(); Bundle args = new Bundle(); args.putInt("position", position); wp.setArguments(args); return wp; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { FrameLayout fl = new FrameLayout(getActivity()); fl.setId(10000); if (getChildFragmentManager().findFragmentByTag("initialTag") == null) { InitialInnerFragment iif = new InitialInnerFragment(); Bundle args = new Bundle(); args.putInt("position", getArguments().getInt("position")); iif.setArguments(args); getChildFragmentManager().beginTransaction() .add(10000, iif, "initialTag").commit(); } return fl; } // required because it seems the getChildFragmentManager only "sees" // containers in the View of the parent Fragment. @Override public void onReplace(Bundle args) { if (getChildFragmentManager().findFragmentByTag("afterTag") == null) { InnerFragment iif = new InnerFragment(); iif.setArguments(args); getChildFragmentManager().beginTransaction() .replace(10000, iif, "afterTag").addToBackStack(null) .commit(); } } } // the fragment that would initially be in the wrapper fragment public static class InitialInnerFragment extends Fragment { private ReplaceListener mListener; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mListener = (ReplaceListener) this.getParentFragment(); LinearLayout ll = new LinearLayout(getActivity()); Button b = new Button(getActivity()); b.setGravity(Gravity.CENTER_HORIZONTAL); b.setText("Frame " + getArguments().getInt("position")); b.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Bundle args = new Bundle(); args.putInt("positionInner", getArguments().getInt("position")); if (mListener != null) { mListener.onReplace(args); } } }); ll.setOrientation(LinearLayout.VERTICAL); ll.addView(b, new LinearLayout.LayoutParams(250, LinearLayout.LayoutParams.WRAP_CONTENT)); return ll; } } public static class InnerFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { TextView tv = new TextView(getActivity()); tv.setText("InnerFragment in the outher Fragment with position " + getArguments().getInt("positionInner")); return tv; } } public interface ReplaceListener { void onReplace(Bundle args); } 

При быстром просмотре он работает, но могут возникнуть проблемы, поскольку я не тестировал его много.

Может ли кто-нибудь показать простой пример того, как это сделать?

Использование вложенных фрагментов кажется довольно простым, пока Commonsware не предложит более продуманный образец, который вы можете попробовать:

 public class NestedFragments extends FragmentActivity { @Override protected void onCreate(Bundle arg0) { super.onCreate(arg0); ViewPager vp = new ViewPager(this); vp.setId(5000); vp.setAdapter(new MyAdapter(getSupportFragmentManager())); setContentView(vp); } private static class MyAdapter extends FragmentPagerAdapter { public MyAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return WrapperFragment.newInstance(position); } @Override public int getCount() { return 8; } } public static class WrapperFragment extends Fragment { public static WrapperFragment newInstance(int position) { WrapperFragment wp = new WrapperFragment(); Bundle args = new Bundle(); args.putInt("position", position); wp.setArguments(args); return wp; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { LinearLayout ll = new LinearLayout(getActivity()); FrameLayout innerFragContainer = new FrameLayout(getActivity()); innerFragContainer.setId(1111); Button b = new Button(getActivity()); b.setText("Frame " + getArguments().getInt("position")); b.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { InnerFragment innerFragment = new InnerFragment(); Bundle args = new Bundle(); args.putInt("positionInner", getArguments().getInt("position")); innerFragment.setArguments(args); FragmentTransaction transaction = getChildFragmentManager() .beginTransaction(); transaction.add(1111, innerFragment).commit(); } }); ll.setOrientation(LinearLayout.VERTICAL); ll.addView(b, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); ll.addView(innerFragContainer, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)); return ll; } } public static class InnerFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { TextView tv = new TextView(getActivity()); tv.setText("InnerFragment in the outher Fragment with position " + getArguments().getInt("positionInner")); return tv; } } } 

Я был ленив и делал все в коде, но я уверен, что он может работать с раздутыми XML-макетами.

Я создал ViewPager с 3 элементами и 2 подэлементами для индекса 2 и 3, и вот что я хотел сделать.

Введите описание изображения здесь

Я реализовал это с помощью предыдущих вопросов и ответов от StackOverFlow, и вот ссылка.

ViewPagerChildFragments