简体   繁体   中英

ViewPager and fragments — design nested fragments or ..?

Docs say you shouldn't nest fragments 'cause they are designed to work another way. But!

Scope

But what if I use ViewPager and it's fragment (visible screen) should be constructed from other fragments. Let's say we have a messenger app. On the main screen there's a ViewPager with fragment called "Last messages" (MessagesFragment) and on the submain screen (let's say Discussion or Chat room) we also have a ViewPager but Messages screen consists of MessagesFragment, NewMessageBarFragment and eg header fragment with other info.

Problem

One can say we shouldn't use ViewPager for that and we can use ViewFlow open source library but believe me the code, holded in such activity is a mess even with fragments. Also there's an approach to fill extra layouts, not fragments for NewMessageBar and HeaderInfo within MessagesFragment — but it's double ugly as for me.

Question

Is it OK to use nested fragments in this particular situation? What would you recommend?

Upadate

Sometimes it's really 'must have' feature. But! In most cases I would recommend follow 'responsive design' way: http://www.slideshare.net/kirillcool/responsive-mobile-design-in-practice

A quick update:

Nested Fragment s were officially introduced in Android API version 17 .

But what if I use ViewPager and it's fragment (visible screen) should be constructed from other fragments.

Don't do that.

Is it OK to use nested fragments in this particular situation?

Absolutely not .

What would you recommend?

Replace your "outer" fragments with simple layouts. Then use some other PagerAdapter implementation that does not itself require a fragment (as does the FragmentPagerAdapter interface). You may need to pinch some code from FragmentPagerAdapter to make sure this all works well.

Or, combine "MessagesFragment, NewMessageBarFragment and eg header fragment with other info" into a single fragment for use on screen sizes where you want to have this pager behavior. This may result in some amount of code duplication, to have that portion of the UI broken out separately for smaller screen sizes.

Here is my solution. Now you can user getChildFragmentManager from fragment. It is included in new SupportLibrary. In my production solution I first test if fragments exist and add them only when necessary.

public class TestActivity extends SherlockFragmentActivity {

    private ViewPager mPager;

    @Override
    protected void onCreate(Bundle arg0) {
        super.onCreate(arg0);
        setContentView(R.layout.pager);
        mPager = (ViewPager) findViewById(R.id.viewPager);
        mPager.setAdapter(new TestAdapter(getSupportFragmentManager()));
    }

    public class TestAdapter extends FragmentStatePagerAdapter {

        public TestAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return TestFragment.newInstance(position);
        }

        @Override
        public int getCount() {
            return 4;
        }
    }

    public static class TestFragment extends SherlockFragment {

        private static final int ID = 9129345;
        private static final String ARG_INDEX = "TestFragment.pageindex";

        public static TestFragment newInstance(int page) {
            TestFragment fragment = new TestFragment();
            Bundle args = new Bundle();
            args.putInt(ARG_INDEX, page);
            fragment.setArguments(args);
            return fragment;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.root_container, null);
            int pageId = getArguments().getInt(ARG_INDEX);

            FragmentTransaction transaction = getChildFragmentManager().beginTransaction();

            transaction.add(R.id.live_radio, TextFragment.newInstance("PAGE", pageId + 1));
            transaction.add(R.id.breaking_news, TextFragment.newInstance("TEXT", 1));
            transaction.add(R.id.main_container, TextFragment.newInstance("TEXT", 2));


            transaction.commit();

            return view;
        }

    }

    public static class TextFragment extends SherlockFragment {

        private static final String ARG_INDEX = "TextFragment.index";
        private static final String ARG_TEXT = "TextFragment.text";

        public static TextFragment newInstance(String text, int index) {
            TextFragment fragment = new TextFragment();
            Bundle args = new Bundle();
            args.putString(ARG_TEXT, text);
            args.putInt(ARG_INDEX, index);
            fragment.setArguments(args);
            return fragment;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,   Bundle savedInstanceState) {
            TextView textView = new TextView(getActivity());
            textView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
            textView.setText(getArguments().getString(ARG_TEXT) + " " + getArguments().getInt(ARG_INDEX));
            return textView;
        }

    }

}

Main Layout with viewpager

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
        android:id="@+id/player"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true" />

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/player"
        android:layout_alignParentTop="true" >
    </android.support.v4.view.ViewPager>

</RelativeLayout>

Fragment layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <FrameLayout
        android:id="@+id/live_radio"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <FrameLayout
        android:id="@+id/breaking_news"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <FrameLayout
        android:id="@+id/main_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1" />

</LinearLayout>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM