更改屏幕旋转时ViewPager片段消失

时间:2013-08-06 09:02:48

标签: java android android-fragments android-viewpager

我正在处理包含ViewPagerFragment s的Android应用程序,如下所示:

MainActivityMainActivityFragmentscreenSlideViewPagerFragment s))),表示:

Activity 包含 Fragment 包含 ViewPager 包含 Fragment s

现在我的问题是当旋转设备或更改屏幕旋转时,ViewPager中的所有片段都会消失。

解决这个问题的任何想法?

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

编辑2 The Activity After Screen Rotation

显然已加载MainActivityMainActivityFragment,证明为ActionBar, 另请注意,ViewPager也已加载,因为您仍然可以在页面之间导航(蓝灯表示寻呼机已到达最后一页),但您无法看到其内容。

8 个答案:

答案 0 :(得分:19)

当您的片段使用getFragmentManager()时,您的主要活动似乎正在使用getSupportFragmentManager()。

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

编辑:我相信您可能还需要使用支持库扩展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;
        }
    }
}

答案 1 :(得分:5)

我尝试了很多解决方案但在任何一个方面都取得了成功。最后我修复如下:

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

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

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

对我而言,它的工作方式就像魅力一样,请在这里评论你的观点。

答案 2 :(得分:3)

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

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

问题是你有一个拥有Fragment的Activity,它拥有拥有多个Fragments的ViewPager。碎片中有片段! Fragments的原始设计并没有真正处理这个用例,后来又进行了更新以处理它。如果碎片中有片段,则需要使用:

Fragment.getChildFragmentManager()

Fragment内,您可以选择Fragment.getFragmentManager(),返回FragmentManager vs Activity的{​​{1}},返回Fragment.getChildFragmentManager()对于FragmentManager FragmentFragment Fragment #include <Servo.h> #include "SoftwareSerial.h"; int servoPin = 2; int bluetoothTx = 11; int bluetoothRx = 10; SoftwareSerial bluetooth(bluetoothTx, bluetoothRx); Servo myservo; char unChar; String readString; void setup() { Serial.begin(9600); bluetooth.begin(115200); delay(100); bluetooth.begin(9600); myservo.attach(servoPin, 800, 2200); } void loop() { if (bluetooth.available()) { unChar = bluetooth.read(); Serial.println(unChar); if (unChar == 'A') { motor(); } } } void motor() { delay(15); while (bluetooth.available()) { char c = bluetooth.read(); readString += c; } if (readString.length() > 0) { Serial.println(readString.toInt()); myservo.write(readString.toInt()); readString = ""; } } 。{/ 1}}

答案 3 :(得分:3)

对于遇到此问题的人,您可以尝试:

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

我花了两天时间解决这个问题,这是唯一对我有用的东西,请记住添加android:configChanges =&#34; screenSize | orientation&#34;你在清单中的活动

答案 4 :(得分:1)

避免再次创建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;
}

答案 5 :(得分:1)

您应该使用getChildFragmentManager()代替getFragmentManager()。   你用过

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

应该是

mPageAdapter = new ScreenSlidePagerAdapter(getActivity().getChildFragmentManager());
片段中的

答案 6 :(得分:1)

在我的情况下,活动A具有片段F1,该片段具有viewpager V1,其具有片段F2,其具有viewpager V2,其具有片段F3。 :)

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

我的解决方法是:

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

编辑

例如,当需要用F2中的V2替换F1中的V1时,

  1. 在V1内用F1_container id封闭相对布局
  2. 使用getSupportFragmentManager()并开始交易
  3. 删除F1
  4. 用F2替换F1_container
  5. 添加到Backstack
  6. 提交交易

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

并认为,花了一天多的时间来更改这些内容并重新启动应用程序,然后查看结果。希望这会有所帮助。

答案 7 :(得分:0)

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