31

I'm working on android application that contains ViewPager with Fragments, like this:

MainActivity(MainActivityFragment(screenSlideViewPager(Fragments))), which means:

Activity contains Fragment contains ViewPager contains Fragments

Now my problem is when rotate device or change screen rotation all Fragments in ViewPager are disappear.

any ideas to solve this issue?

EDIT 1

MainActivity.java:

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

    if (getSupportFragmentManager().findFragmentByTag(TAG) == null) {
        final FragmentTransaction ft = getSupportFragmentManager()
                .beginTransaction();
        ft.add(android.R.id.content, new MainActivityFragment(), TAG);
        ft.commit();
    }
}

MainActivityFragment.java:

public class MainActivityFragment extends Fragment {
    private ViewPager mPager = null;
    private PagerAdapter mPageAdapter = null;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final View reVal = inflater.inflate(R.layout.activity_main, container, false);
        mPager = (ViewPager) reVal.findViewById(R.id.pagerMainContent);
        mPageAdapter = new ScreenSlidePagerAdapter(getActivity().getFragmentManager());
        mPager.setAdapter(mPageAdapter);
        return reVal;
    }

    private MainGridViewFragment mainGridFragment;
    private AlphabetGridViewFragment alphabetGridFragment;

    private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
        public ScreenSlidePagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public android.app.Fragment getItem(int position) {
            switch (position) {
                case 1:
                    mainGridFragment = new MainGridViewFragment();
                    return mainGridFragment;
                case 0:
                    alphabetGridFragment = new AlphabetGridViewFragment();
                    return alphabetGridFragment;
                default:
                    return null;
            }
        }

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

EDIT 2 The Activity After Screen Rotation

Obviously MainActivity and MainActivityFragment are loaded, and the proof is The ActionBar, notice also that ViewPager is loaded too, because you still can navigate between pages (the blue light means that the pager reached to last page) but you can't see its content.

4

8 回答 8

20

看起来您的主要活动正在使用 getSupportFragmentManager(),而您的片段正在使用 getFragmentManager()。

不确定这是否值得回复,但我的评分太低,无法以任何其他方式回复。:)

编辑:我相信您可能还需要使用支持库扩展 FragmentActivity。

请参阅:https ://stackoverflow.com/a/10609839/2640693

编辑2:

public class MainActivityFragment extends FragmentActivity {
    private ViewPager mPager = null;
    private PagerAdapter mPageAdapter = null;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final View reVal = inflater.inflate(R.layout.activity_main, container, false);
        mPager = (ViewPager) reVal.findViewById(R.id.pagerMainContent);
        mPageAdapter = new ScreenSlidePagerAdapter(getChildFragmentManager());
        mPager.setAdapter(mPageAdapter);
        return reVal;
    }

    private MainGridViewFragment mainGridFragment;
    private AlphabetGridViewFragment alphabetGridFragment;

    private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
        public ScreenSlidePagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            switch (position) {
                case 1:
                    mainGridFragment = new MainGridViewFragment();
                    return (Fragment)mainGridFragment;
                case 0:
                    alphabetGridFragment = new AlphabetGridViewFragment();
                    return (Fragment)alphabetGridFragment;
                default:
                    return null;
            }
        }

        @Override
        public int getCount() {
            return 2;
        }
    }
}
于 2013-08-06T09:41:35.497 回答
9

我尝试了许多解决方案,但在任何一个中都获得了成功。最后我固定如下:

  • 使用 getActivity().getSupportFragmentManager() 而不是 getChildFragmentManager()

  • 覆盖 ViewPagerAdapter 类中的 getItemId(int position) 方法,如下所示:

    @Override
    public long getItemId(int position) {
        return System.currentTimeMillis();
    }
    

对我来说,它就像魅力一样,也请在这里评论你的观点。

于 2016-10-14T08:51:56.443 回答
5

对于有此问题的人,您可以尝试以下操作:

private void InitializeUI(){
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);

}

@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.activity_exame2);
InitializeUI();
}

我花了 2 天时间解决这个问题,这是唯一对我有用的东西,请记住将 android:configChanges="screenSize|orientation" 添加到清单中的活动中

于 2016-08-18T21:22:52.067 回答
3

避免再次创建 viewpager。将 onCreateView 的代码放在 onCreate() 中。并使您的片段使用 onRetainInstance(true)。因此,这不应重新创建片段,因为视图位于 onCreate() 中,因此不会再次调用它。

检查 onCreateView() 视图是否存在,如果存在则删除它。片段:

//creates the view
private View createView(Bundle savedInstanceState) {
    View view = getActivity().getLayoutInflater().inflate(your_layout, null, false);

    //viewpager

    return view;
}

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

    //retains fragment instance across Activity re-creation
    setRetainInstance(true);

    viewRoot = createView(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    if (viewRoot != null && viewRoot.getParent() != null) {
        ViewGroup parent = (ViewGroup) viewRoot.getParent();
        parent.removeView(viewRoot);

        Log.i("Test", "**************view.getParent(): " + viewRoot.getParent() + "    " + viewRoot);
    }

    return viewRoot;
}
于 2013-08-06T10:39:21.063 回答
3

我有这个完全相同的问题。这非常令人困惑,但是这个线程帮助了我,除了答案并没有真正解释它为什么起作用。

解决此问题的方法是使用Fragment.getChildFragmentManager(). 令人困惑的是 android API 有Activity.getFragmentManager(),但如果您尝试支持旧设备,则需要使用Activity.getSupportFragmentManager(). 但是,这个特殊问题与支持旧 API 无关。

问题是你有一个 Activity,它有一个 Fragment,它拥有 ViewPager,它拥有几个 Fragment。你有片段中的片段!Fragments 的原始设计并没有真正处理这个用例,后来被更新来处理它。当您在片段中有片段时,您需要使用:

Fragment.getChildFragmentManager()

在 a中,Fragment您可以选择Fragment.getFragmentManager()哪个返回vs哪个返回for this正确限定s 中的.FragmentManagerActivityFragment.getChildFragmentManager()FragmentManagerFragmentFragmentFragment

于 2016-06-25T13:16:42.170 回答
1

您应该使用 agetChildFragmentManager()而不是getFragmentManager(). 你用过

mPageAdapter = new ScreenSlidePagerAdapter(getActivity().getFragmentManager());

应该是

mPageAdapter = new ScreenSlidePagerAdapter(getActivity().getChildFragmentManager());

在你的片段中

于 2015-05-18T18:00:05.080 回答
1

在我的例子中,活动 A 有片段 F1,它有 viewpager V1,它有片段 F2,它有 viewpager V2,它有片段 F3。:)

最后一个片段 F3 在旋转时会给出空白或错误​​。

我的解决方案是:

  1. 移除 PageChangeListener,所以在更改 Fragment 时基本不使用 Fragment 事务,而是保持默认。
  2. 使用 FragmentStatePagerAdapter 而不是 FragmentPagerAdapter
  3. 覆盖适配器中的 getItemPosition() 并返回 POSITION_NONE
  4. 在适配器中创建一个包含片段列表的字段并在构造函数中设置它
  5. 在适配器的 getItem() 中只返回 fragmentList.get(position)
  6. 在适配器的 getCount() 中只返回 fragmentList.size()
  7. 不要覆盖适配器中的任何其他方法,例如销毁、实例化等
  8. 在 F2 的 onCreateView() 中创建并实例化 V2 适配器

编辑

例如,当需要将 F1 中的 V1 替换为 F2 中的 V2 时:

  1. 用 F1_container id 将 V1 包含在相对布局中
  2. 使用 getSupportFragmentManager() 并开始交易
  3. 删除 F1
  4. 用 F2 替换 F1_container
  5. 添加到后台
  6. 提交事务

稍后当需要从 F2 恢复到 F1 时,在有效的 A 引用上调用 popBackStack()。

并且认为就是这样,花了一天多的时间来更改每个这些并重新启动应用程序并查看结果。希望这可以帮助。

于 2019-03-02T01:04:21.747 回答
0

我一直在使用数据绑定,同时让片段 A 托管 viewPager,到目前为止,旋转不是问题,而是导航到片段 B 并返回,然后旋转是问题。原来我正在分配parentFragmentManager而不是childFragmentManager. 这是Android开发的基本原理,我很尴尬地忘记了这一点:)

于 2020-06-04T17:42:21.167 回答