如何使用嵌套片段(Android 4.2)在ViewPager中添加片段

我有一个ViewPager与三个Fragments ,每个显示一个List (或Grid )。

在新的Android API level 17 (Jelly Bean 4.2)中,其中一个特性是嵌套片段 。 新的function描述说:

如果您使用ViewPager创build左右滑动并占用大部分屏幕空间的片段,则现在可以将片段插入到每个片段页面中。

所以,如果我理解正确的话,现在我可以在里面创build一个带FragmentsViewPager (例如里面有一个button),当用户按下button显示另一个Fragment不会松动ViewPager使用这个新function。

我已经花了我的早晨试图实现这几种不同的方式,但我不能让它工作…有人可以添加一个简单的例子来说明如何实现这个?

PS:我只对这样做有兴趣,用getChildFragmentManager来学习如何工作。

假设你已经创build了正确的XML布局。 在另一个片段托pipe的ViewPager中显示片段现在非常简单。

代码在父Fragment中看起来像这样:

  @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() ,否则你会得到一个exception。

源代码可以在 https://github.com/marcoRS/nested-fragments find

编辑:如果您想要replaceViewPager中的页面的所有内容,您仍可以使用嵌套的片段,但需要进行一些更改。 检查下面的示例( FragmentActivity ,设置ViewPagerPagerAdapter与前面的代码片段相同):

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

快速查看它的作品,但问题可能会出现,因为我没有testing过多。

有人可以展示一个简单的例子,如何做到这一点?

使用嵌套片段似乎很容易,直到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布局。

我已经为索引2和3创build了一个具有3个元素和2个子元素的ViewPager,这里是我想要做的。

在这里输入图像描述

我已经在StackOverFlow的以前的问题和答案的帮助下实现了这一点,这里是链接。

ViewPagerChildFragments