ViewPager 和片段 —设计嵌套片段或..?

发布于 2024-12-12 13:18:45 字数 744 浏览 0 评论 0原文

文档说你不应该嵌套片段,因为它们被设计成以另一种方式工作。但!

范围

但是,如果我使用 ViewPager 并且它的片段(可见屏幕)应该由其他片段构建,该怎么办?假设我们有一个消息应用程序。在主屏幕上有一个 ViewPager,其中包含名为“最后消息”(MessagesFragment) 的片段,在子主屏幕(比如说讨论室或聊天室)上,我们也有一个 ViewPager,但消息屏幕由 MessagesFragment、NewMessageBarFragment 和例如带有其他信息的标题片段组成。

问题

一可以说我们不应该为此使用 ViewPager,我们可以使用 ViewFlow 开源库,但相信我,在此类活动中举行的代码即使有碎片也是一团糟。还有一种方法可以填充额外的布局,而不是 MessagesFragment 中的 NewMessageBar 和 HeaderInfo 的片段 - 但对我来说它是双重丑陋的。

问题

在这种特殊情况下可以使用嵌套片段吗?你会推荐什么?

更新

有时它确实是“必须具备”的功能。但!在大多数情况下,我建议遵循“响应式设计”方式: http:// /www.slideshare.net/kirillcool/responsive-mobile-design-in-practice

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 e.g. 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

对风讲故事 2024-12-19 13:18:45

快速更新:

嵌套 Fragment 已在 Android 中正式引入API 版本 17

A quick update:

Nested Fragments were officially introduced in Android API version 17.

南风起 2024-12-19 13:18:45

但是如果我使用 ViewPager 并且它的片段(可见屏幕)应该由其他片段构建,该怎么办?

不要那样做。

在这种特殊情况下可以使用嵌套片段吗?

绝对不是

你会推荐什么?

用简单的布局替换“外部”片段。然后使用其他一些本身不需要片段的 PagerAdapter 实现(如 FragmentPagerAdapter 接口)。您可能需要从 FragmentPagerAdapter 中提取一些代码以确保这一切正常工作。

或者,将“MessagesFragment、NewMessageBarFragment 以及例如带有其他信息的标题片段”组合到单个片段中,以便在您希望具有此寻呼机行为的屏幕尺寸上使用。这可能会导致一定量的代码重复,以便针对较小的屏幕尺寸单独分解 UI 的该部分。

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 e.g. 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.

肤浅与狂妄 2024-12-19 13:18:45

这是我的解决方案。现在您可以从片段中使用 getChildFragmentManager 。它包含在新的支持库中。在我的生产解决方案中,我首先测试片段是否存在,并仅在必要时添加它们。

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

    }

}

主布局与 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>

片段布局

<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>

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文