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

sab*_*dow 55 android android-fragments android-viewpager android-support-library android-nested-fragment

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

在新的Android API level 17(Jelly Bean 4.2)中,其中一个功能是嵌套片段.新功能描述说:

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

所以,如果我理解正确的话,现在我可以在里面创建一个ViewPagerwith Fragments(里面有一个按钮),当用户按下按钮时显示另一个Fragment没有松动ViewPager使用这个新功能.

我已经花了我的早上尝试实现这几种不同的方式,但我不能让它工作......有人可以添加一个如何实现这个的简单示例吗?

PS:我只对这种方式感兴趣,getChildFragmentManager学习如何运作.

Mar*_* RS 100

假设您已创建正确的xml布局.现在,在由另一个片段托管的ViewPager中显示片段非常简单.

以下是显示子片段的父片段:

class ParentViewPagerFragment : Fragment() {

  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val root = inflater.inflate(R.layout.fragment_parent_viewpager, container, false)

    val viewPager = root.findViewById(R.id.viewPager) as ViewPager
    // Important: Must use the child FragmentManager or you will see side effects.
    viewPager.adapter = MyAdapter(childFragmentManager)

    val tabStrip = root.findViewById<TabLayout>(R.id.pagerTabStrip)
    tabStrip.setupWithViewPager(viewPager)

    return root
  }

  class MyAdapter internal constructor(fm: FragmentManager) : FragmentPagerAdapter(fm) {

    override fun getCount(): Int = 4

    override fun getItem(position: Int): Fragment {
      val args = Bundle().apply { putInt(ChildFragment.POSITION_KEY, position) }
      return ChildFragment.newInstance(args)
    }

    override fun getPageTitle(position: Int): CharSequence = "Tab $position"
  }

  companion object {
    val TAG: String = ParentViewPagerFragment::class.java.name
  }
}
Run Code Online (Sandbox Code Playgroud)

在实例化FragmentPagerAdapter时使用Fragment.getChildFragmentManager()非常重要.另请注意,您不能对子片段使用Fragment.setRetainInstance(),否则您将获得异常.为简洁起见,省略了进口.

源代码可在以下 网址找到:https ://github.com/marcoRS/nested-fragments

  • 发现我的FragmentPagerAdapter实现了自己的isViewObject方法,这在将ViewPager嵌套在自己的片段之前不是问题,一旦删除我现在看到页面:)拉出你的代码并运行它以增强我的信心和渴望让它工作 - 谢谢Marco! (2认同)

Luk*_*rog 12

编辑: 如果要替换页面中的所有内容,ViewPager您仍然可以使用嵌套片段,但需要进行一些更改.检查下面的示例(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);
}
Run Code Online (Sandbox Code Playgroud)

快速查看它是否有效,但问题可能会出现,因为我还没有对它进行过多次测试.

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

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

    }

}
Run Code Online (Sandbox Code Playgroud)

我很懒,并且在代码中做了所有事情,但我确信它可以使用膨胀的xml布局.

  • @CommonsWare我实际上希望使用它.无论如何,我已经测试了将`getChildFragmentManager`传递给`PagetAdapter`设置为`Fragment`中包含的`ViewPager`并且它运行良好. (2认同)

Ruk*_*ias 6

我已经为索引2和3创建了一个包含3个元素和2个子元素的ViewPager,这就是我想要做的事情.

在此输入图像描述

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

ViewPagerChildFragments