ViewPager fragments disappear when change screen r

2019-01-22 06:37发布

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.

6条回答
老娘就宠你
2楼-- · 2019-01-22 06:56

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

查看更多
ら.Afraid
3楼-- · 2019-01-22 06:58

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.

查看更多
老娘就宠你
4楼-- · 2019-01-22 07:02

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

查看更多
▲ chillily
5楼-- · 2019-01-22 07:12

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;
}
查看更多
【Aperson】
6楼-- · 2019-01-22 07:16

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.

查看更多
劫难
7楼-- · 2019-01-22 07:18

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;
        }
    }
}
查看更多
登录 后发表回答