【问题标题】:Why it is not possible to use ViewPager within a Fragment? It actually is为什么不能在 Fragment 中使用 ViewPager?它实际上是
【发布时间】:2012-08-23 09:48:02
【问题描述】:

有信息表明,在许多来源(如 Mark Murphy 的“The Busy Coders Guide for Android Developers”)或 SO 上的 this 等帖子中,不可能在 Fragment 中使用 ViewPager。我很困惑,因为我没有这样的问题,并且我在Fragment 中成功使用了ViewPager。唯一的区别是我不是在onCreateView() 方法中而是在onActivityCreated() 中实例化ViewPager。一切正常。

所以问题是 - 可能我只是不知道一些事情,并且出于某种原因不建议在 onActivityCreated() 中进行 UI 实例化?但同样 - 一切正常。

这是类和xml的列表:

类:

public class ViewPagerFragment extends Fragment {

    static final int NUM_ITEMS = 2;

    private ViewPagerAdapter mAdapter;
    private ViewPager mPager;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.view_pager_fragment, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        mAdapter = new ViewPagerAdapter(getFragmentManager());

        mPager = (ViewPager) getView().findViewById(R.id.pager);
        mPager.setAdapter(mAdapter);
    }

    public static class ViewPagerAdapter extends FragmentPagerAdapter {
        public ViewPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int num) {
            if (num == 0) {
                return new ItemsListFragment();
            } else {
                return new FavsListFragment();
            }
        }

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

布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:orientation="vertical">

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

</LinearLayout>

【问题讨论】:

标签: android android-fragments android-viewpager commonsware


【解决方案1】:

要在片段中实现视图分页器,请使用 getChildFragmentManager() 而不是 getFragmentManager()。您可以从 onCreateView()onViewCreated() 为 ViewPager 调用 setAdapter(),这不是问题。

希望对大家有所帮助。

【讨论】:

  • @Raj,你能提供一个样本吗?
  • 微妙却又如此重要。
  • @AlexChe 你能分享一下代码 sn-p 吗?我似乎无法实现它。
【解决方案2】:

更新:由于这个答案最初是写的,你现在可以有嵌套的片段,这意味着可以有一个 ViewPager 使用页面的片段在片段本身中。 This sample project 演示了该技术。

我现在返回您定期安排的答案,完整呈现...


引用书中自己的话:

使用 ViewPager 最简单的方法是让它的页面片段进出 基于用户滑动的屏幕。这仅在不包含 ViewPager 本身的情况下才有效 在一个片段中,因为您不能将片段嵌套在其他片段中。

引用Dianne Hackborn

目前不支持嵌套片段。尝试将片段放在另一个片段的 UI 中会导致未定义且可能会损坏的行为。

完全可以将ViewPager 放在Fragment 中,只要ViewPager内容本身不包含片段。由于 Android Support 包提供的PagerAdapter 的具体实现使用了片段,因此您必须滚动自己的无片段PagerAdapter 才能将ViewPager 放入片段中。

我会努力在本书的下一版中更清楚地说明这一点(除非你是英国人,在这种情况下,我会努力让这一点更清楚:-)。

【讨论】:

  • 我不是英国人 :) 感谢您的回复。你能在onActivityCreated() 方法中添加一些关于 UI 实例化的内容吗?
  • 好消息,4.2 支持嵌套片段。见Android 4.2 APIs
  • 嘿@Co​​mmonsWare,感谢您的链接。你是对的,它确实适用于旧设备。我之前遇到的问题是当我在 ListView Header 中有 Fragments 的 ViewPager 时(使用 addHeaderView())。 ListView 本身也在一个片段内。我打印了 onDestroy() 和 onCreate() 方法调用,基本上,在旋转时,viewpager 中的片段没有被破坏。因此泄漏了碎片。你见过这样的事情吗?
  • @clu:您指出的唯一可以正常工作的方法是使用嵌套片段(例如,ViewPager 正在使用子 FragmentManager)。如果你是,那么理论上应该没有问题,但是嵌套片段通常有时会出现问题,所以我尽量避免它们。
  • 嗨@CommonsWare,对不起,我刚想回复这个!谢谢您的帮助。我实际上想通了这一点。基本上我在 getItem() 调用中传递了适配器已经创建的片段。这是错误的,因为在旋转之后,FragmentManager 会重新实例化它们。然后我尝试访问原始的、已创建的片段,片段管理器不再使用这些片段。我通过返回一个在 getItem() 中创建片段的适配器来解决此问题。
【解决方案3】:

在为 ViewPager 初始化 SetionPageAdapter 时,使用“getChildFragmentManager()”。

mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());

【讨论】:

    【解决方案4】:

    可以尝试执行此代码并保存 view_pager_fragment.xml

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBarLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
    
        <android.support.design.widget.TabLayout
            android:id="@+id/tab"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    
    </android.support.design.widget.AppBarLayout>
    
    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
    

    ViewPagerFragment

    ViewPager viewPager;
    TabLayout tabLayout;
    
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.tracks, container, false);
    
        viewPager = (ViewPager) view.findViewById(R.id.viewpager);
        tabLayout = (TabLayout) view.findViewById(R.id.tab);
    
        return view;
    }
    
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    
        setupViewPager(viewPager);
        tabLayout.setupWithViewPager(viewPager);
    
        tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
    
            }
    
            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
    
            }
    
            @Override
            public void onTabReselected(TabLayout.Tab tab) {
    
            }
        });
    }
    
    private void setupViewPager(ViewPager viewPager) {
        ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager());``
    
    
        viewPager.setAdapter(viewPagerAdapter);
    }
    
    public class ViewPagerAdapter extends FragmentStatePagerAdapter {
        public ViewPagerAdapter(FragmentManager manager) {
            super(manager);
        }
    
        @Override
        public Fragment getItem(int position) {
            if(position == 0) return new SampleFragment();
            if(position == 1) return new SampleFragment2();
            if(position == 2) return new SampleFragment3();
            throw new IllegalStateException("Unexpected position " + position);
        }
    
        @Override
        public int getCount() {
            return 3;
        }
    
        @Override
        public CharSequence getPageTitle(int position) {
            if(position == 0) return "Tab 1";
            if(position == 1) return "Tab 2";
            if(position == 2) return "Tab 3";
            throw new IllegalStateException("Unexpected position " + position);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-27
      • 1970-01-01
      相关资源
      最近更新 更多