恢复时不恢复ViewPager中的片段视图

时间:2014-02-21 11:00:29

标签: android android-fragments android-tabs

我有ActionBar标签设置。它由4个标签组成。一切都很好,直到我离开TabbedFragment并返回。

我创建了这样的标签:

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

        final ActionBar actionBar = getActionBar();

        tabs = Lists.newArrayList();
        tabs.add(new TabDefinition<>("Tab 1"));
        tabs.add(new TabDefinition<>("Tab 2"));
        tabs.add(new TabDefinition<>("Tab 3"));
        tabs.add(new TabDefinition<>("Tab 4"));


        for (TabDefinition tab : tabs) {
            actionBar.addTab(actionBar.newTab()
                .setText(tab.text)
                .setTag(tab.tag)
                .setTabListener(this));
        }
    }

并像这样初始化适配器:

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

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    viewPager = (ViewPager) view.findViewById(R.id.pager);

    viewPager.setAdapter(new FragmentStatePagerAdapter(getFragmentManager()) {

        @Override
        public Fragment getItem(int position) {
            return tabs.get(position).fragment;
        }

        @Override
        public int getCount() {
            return tabs.size();
        }
    });

    viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
            getActionBar().setSelectedNavigationItem(position);
        }
    });

    viewPager.setCurrentItem(getActionBar().getSelectedNavigationIndex(), true);
}

当返回TabbedFragment所选标签时,其旁边的1将没有任何内容。只是空视图。但是,如果我选择当前+ 2片段内容加载。然后返回到第一个片段内容重新加载 例如,我有A,B,C,D标签。在离开TabbedFragment之前,我选择了标签A. 返回TabbedFragment时,我仍然在标签A,但它是空的。标签B也是如此 但是当选择选项卡C时,它会被创建并加载。返回标签A,重新创建。

这可能是什么问题?

6 个答案:

答案 0 :(得分:63)

一段时间后再遇到同样的问题,所以更新这个问题。 如果您使用的是FragmentStatePagerAdapter,则应通过FragmentManager代替getChildFragmentManager()提供getFragmentManager()。见Issue 55068: ViewPager doesn't refresh child fragments when back navigation via backstack

答案 1 :(得分:3)

好的,当使用FragmentStatePagerAdapter时,当您导航的片段超过一个片段时,您的片段将被销毁,因为默认情况下offScreenPageLimit默认设置为1,如上所述。

通常,此类用于具有非常大的Fragments集的活动,即必须滚动浏览大量视图。如果您的应用程序不需要超过3-4个选项卡,我建议使用FragmentPagerAdapter代替,然后将offScreenPageLimit指定为类似3,所以如果你到达第4个选项卡,之前的所有3个选项卡仍然是在记忆中。

以下是我在github上创建的项目的一些示例代码,说明了如果您不想添加此offScreenPageLimit,如何动态加载片段。

https://github.com/lt-tibs1984/InterfaceDemo/blob/master/src/com/divshark/interfacedemo/InterfaceDemoMain.java

遍历此类中的所有代码,每次ViewPager滑过时,您都会看到我是如何动态加载片段的。最值得注意的是在底部。

您可以下载此代码,并将其用作您要执行的操作的测试基础。 尝试在viewPager的onCreate()方法中添加setOffScreenPageLimit(2)并注意不同的行为。要检查行为,请编辑片段1中的文本。导航离开并导航回来,使用此设置与否。您将看到它何时被设置,片段的文本仍然是您更改它的内容,因为片段永远不会重新创建。

如果您有这些问题,请提供其他问题。

好运

<强>更新

private static final String [] fragmentClasses = {"com.example.project.YourFragment1","com.example.project.YourFragment2","com.example.project.YourFragment3"};



 viewPager.setAdapter(new FragmentStatePagerAdapter(getFragmentManager()) {

    @Override
    public Fragment getItem(int position) {

       Fragment fragmentAtPosition = null;

       // $$$$ This is the Important Part $$$$$
       // Check to make sure that your array is not null, size is greater than 0 , current position is greater than equal to 0, and position is less than length
       if((fragmentClasses != null) && (fragmentClasses.length > 0)&&(position >= 0)&& (position < fragmentClasses.length))
        {
       // Instantiate the Fragment at the current position of the Adapter
        fragmentAtPosition = Fragment.instantiate(getBaseContext(), fragmentClasses[position]);
        fragmentAtPosition.setRetainInstance(true);

       }

        return fragmentAtPosition;
    }

    @Override
    public int getCount() {
        return fragmentClasses.length;
    }
});

答案 2 :(得分:1)

我认为,您用作标签的片段中存在问题。他们恢复时似乎没有显示任何东西(见Fragment lifecycle)。仅当前选定的+/- 1选项卡为空的“奇怪”问题是因为ViewPager的{​​{3}}默认为1。超过此阈值的所有选项卡都将重新创建。

因此,在您的情况下,增加值将导致所有选项卡在恢复后显示为空。检查Fragment代码中使用哪些生命周期方法来扩充布局,设置适配器等等,因为这会导致您的麻烦。

答案 3 :(得分:1)

我想这是因为加载片段android加载当前和当前+ 1,如果你调试你就不会看到onPause被调用下一个片段。

您可以在TabHost.OnTabChangeListener的onTabChanged()方法中以编程方式重新加载内容。

答案 4 :(得分:0)

经过大量研究,这对我有用。 我有一个复杂的布局,片段中有3个选项卡,可以切换到其他片段。我意识到即使你按下主页按钮,ViewpagerAdapter也会保留状态。我的问题是来回切换会使子片段UI视图元素无效并崩溃。关键是不要newViewPagerAdapter。添加适配器的空检查对我有用。另外,请务必根据您的需要分配setOffscreenPageLimit()。此外,根据我的理解setRetainInstance(true);不应该用于具有UI的片段,它是专为无头片段设计的。

在包含标签的片段中:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_tab, container, false);
    tabLayout = (TabLayout) view.findViewById(R.id.tablayout);
    viewPager = (ViewPager) view.findViewById(R.id.viewPager);

    //Important!!! Do not fire the existing adapter!!
    if (viewPagerAdapter == null) {
        viewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
        viewPagerAdapter.addFragments(new AFragment(), "A");
        viewPagerAdapter.addFragments(new BFragment(), "B");
        viewPagerAdapter.addFragments(new CFragment(), "C");
    }
    //Allocate retention buffers for three tabs, mandatory
    viewPager.setOffscreenPageLimit(3);
    tabLayout.setupWithViewPager(viewPager);
    viewPager.setAdapter(viewPagerAdapter);

    return view;
}

答案 5 :(得分:0)

或者更简单地在导航回tabbedfragment时(假设你使用了一个意图而片段在一个活动中)使用:

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

这会保留原始活动并将其移动到堆栈顶部而不是重新创建它,因此您永远不需要重新创建viewPager。