Home » Android » java – ViewPager fragments disappear when change screen rotation

java – ViewPager fragments disappear when change screen rotation

Posted by: admin April 23, 2020 Leave a comment

Questions:

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.

How to&Answers:

It looks like your main activity is using the getSupportFragmentManager() while your fragment is using getFragmentManager().

Not sure if this is worthy of an answer post but my rating is too low to reply any other way. 🙂

Edit: I believe you may also need to extend a FragmentActivity with the support library.

See: https://stackoverflow.com/a/10609839/2640693

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

Answer:

I tried many solution but get success in any one. At last I fixed as below:

  • Use getActivity().getSupportFragmentManager() rather than getChildFragmentManager()

  • Override getItemId(int position) method in your ViewPagerAdapter class like below:

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

For me it’s working like charm, please also comment here your view.

Answer:

For the ones that are having problems with this you can try this:

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

i spent 2 days around this problem this was the only thing that worked for me, remeber to add android:configChanges=”screenSize|orientation” to your activity in manifest

Answer:

I had this exact same problem. It’s tremendously confusing, but this thread helped me out except that the answers didn’t really explain why it works.

The fix to this problem is to use Fragment.getChildFragmentManager(). What’s so confusing is the android API has Activity.getFragmentManager(), but if you are trying to support older devices you need to use Activity.getSupportFragmentManager(). However, this particular problem isn’t about supporting older APIs.

The problem is that you have a Activity which has a Fragment which owns the ViewPager which owns several Fragments. You have Fragments within Fragments! The original design of Fragments didn’t really handle this use case and later was updated to handle it. When you have Fragments within Fragments you need to use:

Fragment.getChildFragmentManager()

From within a Fragment you have the choice of Fragment.getFragmentManager() which returns the FragmentManager of the Activity vs Fragment.getChildFragmentManager() which returns the FragmentManager for this Fragment which properly scopes the Fragments within your Fragment.

Answer:

Avoid creating the viewpager again. Put the code of onCreateView in onCreate(). And make your fragment use onRetainInstance(true). Hence this shall not recreate the fragment and again because the view is in the onCreate(), it will not be called again.

Check in the onCreateView() whether the view exists, if so then remove it.
Snippets:

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

Answer:

You should rather use a getChildFragmentManager() instead of the getFragmentManager().
You used

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

it should have been

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

in your fragment

Answer:

In my case there is activity A which has fragment F1, which has viewpager V1, which has fragment F2, which has viewpager V2, which has fragment F3. 🙂

This last fragment F3, when rotated, either gives blank or error.

My solution was to:

  1. Remove PageChangeListener, so basicly not use fragment transactions when changing fragments, instead leave as it is default.
  2. Use FragmentStatePagerAdapter instead of FragmentPagerAdapter
  3. Override getItemPosition() in adapter and return POSITION_NONE
  4. Create a field with List of Fragments in adapter and set it in constructor
  5. In getItem() in adapter just return fragmentList.get(position)
  6. In getCount() in adapter just return fragmentList.size()
  7. NOT OVERRIDE any other methods in adapter like destroy, instantiate etc
  8. Create and instantiate V2 adapter in onCreateView() of F2

EDIT

When for example need to replace V1 in F1 with V2 in F2 then:

  1. Enclose V1 inside say relative layout with F1_container id
  2. Use getSupportFragmentManager() and begin transaction
  3. Remove F1
  4. Replace F1_container with F2
  5. Add to backstack
  6. Commit transaction

Later when need to comeback from F2 to F1 call popBackStack() on valid A reference.

And think thats it, took more than a day of changing each of those and restarting app and see result. Hope this helps.