Как добавить фрагмент внутри ViewPager с помощью вложенного фрагмента (Android 4.2)
у меня есть ViewPager
три Fragments
, каждый из них показывает List
(или Grid
).
новый Android API level 17
(желе Bean 4.2), одной из особенностей является Вложенные Фрагменты. Новое описание функциональности говорит:
если вы используете ViewPager для создания фрагментов, которые прокручиваются влево и вправо и потребляйте большую часть пространства экрана, Теперь вы можете вставлять фрагменты в каждый фрагмент страницы.
Итак, если я понимаю правильно, теперь я могу создать ViewPager
с Fragments
(с кнопкой внутри например) внутри, и когда пользователь нажимает кнопку показать другой Fragment
не потерять ViewPager
с помощью этой новой функции.
я потратил свое утро, пытаясь реализовать это несколько разных способов, но я не могу заставить его работать... Может кто-нибудь добавить простой пример того, как это реализовать?
PS: Я заинтересован только в том, чтобы делать таким образом, с getChildFragmentManager
чтобы узнать, как работает.
3 ответа:
предполагая, что вы создали правильные 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); } }
важно использовать фрагмент.getChildFragmentManager () при создании экземпляра FragmentPagerAdapter. Также обратите внимание, что вы не можете использовать фрагмент.setRetainInstance() на фрагменты детей или вы получите исключение.
исходный код можно найти на:https://github.com/marcoRS/nested-fragments
Edit: Если вы хотите заменить все содержимое страницы в
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 макеты.