Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ActionBarSherlock with ViewPager not calling ViewPager fragments lifecycle methods when going to and returning from backstack

I have an application that uses ActionBarSherlock and inside the main fragment I have a ViewPager which uses several fragments to display different objects of a list.

Main Fragment:

    public class CollectionDemoFragment extends SherlockFragment {

    DemoCollectionPagerAdapter mDemoCollectionPagerAdapter;
    ViewPager mViewPager;

    public CollectionDemoFragment() {
        setTitle(R.string.title);
        setHasOptionsMenu(true);
    }

    public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.demo_fragment, container, false);
        mDemoCollectionPagerAdapter = new DemoCollectionPagerAdapter(getFragmentManager());
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mDemoCollectionPagerAdapter);
        return view;
    }

    @Override
    public void onPause() {
        //This runs when the fragment goes to backstack
        super.onPause();
    }

    @Override
    public void onResume() {
        //This runs when the fragment returns from backstack
        super.onResume();
    }
}

ViewPagerAdapter:

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

    @Override
    public Fragment getItem(int i) {
        Fragment fragment = new DemoObjectFragment();
        Bundle args = new Bundle();
        args.putInt(DemoObjectFragment.ARG_OBJECT, i + 1);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

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

    @Override
    public CharSequence getPageTitle(int position) {
        return "OBJECT " + (position + 1);
    }
}

Inside each of this fragments I can create a new Main fragment with a new list to display in the ViewPager and replace the content with this new fragment.

ViewPager Fragments:

public static class DemoObjectFragment extends Fragment {
    public static final String ARG_OBJECT = "object";

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

        View rootView = inflater.inflate(
                R.layout.fragment_collection_object, container, false);
        Bundle args = getArguments();
        ((TextView) rootView.findViewById(android.R.id.text1)).setText(
                Integer.toString(args.getInt(ARG_OBJECT)));
             //Setup components

        return rootView;
    }   

    @Override
    public void setMenuVisibility(final boolean visible) {
        if (visible) {
            //Do something
        }
        super.setMenuVisibility(visible);
    }

    @Override
    public void onPause() {
        //This should run when the fragment goes to backstack
        super.onPause();
    }

    @Override
    public void onResume() {
        //This should run when the fragment returns from backstack
        super.onResume();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.someComponent:
            Fragment newContent = new CollectionDemoFragment();
            switchContent(newContent, true);
            break;
        }
    }

    public void switchContent(Fragment newContent, boolean addToBackStack) {
        if (newContent != null) {
            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
            ft.replace(R.id.content_frame, newContent);
            if (addToBackStack) {
                ft.addToBackStack("" + newContent.getId());
            }
            ft.commit();
        }
    }
}

This works ok, until I press back and the previous main fragment returns from the backstack.

The screen is empty (since onCreateView is not called the layout is not inflated), the lifecycle methods from the fragments in the ViewPager are never called either when the main fragment enters the backstack, nor when it returns . The only method called in the fragments of the ViewPager is the setMenuVisibility() so, only the code in there runs.

Anyone knows a way to fix this and why this happens?

Not sure if it matters but I have to support since android 2.3.

like image 447
Mikel Avatar asked Jan 11 '13 12:01

Mikel


1 Answers

When you are creating the view adapter You have to pass the fragment child manager as argument - getChildFragmentManager() instead of getFragmentManager().

Instead of,

 mDemoCollectionPagerAdapter = new DemoCollectionPagerAdapter(getFragmentManager());

you should use,

 mDemoCollectionPagerAdapter = new DemoCollectionPagerAdapter(getChildFragmentManager());
like image 192
cmota Avatar answered Nov 17 '22 23:11

cmota