1

I am trying to create custom tab navigation. On click on each tab, it will replace fragment in screen. On MainActivity.java, I am creating one copy of each fragment (I think, in this way, I can use one copy of each fragment everywhere).

    public static WhereRootFragment whereRootFragment;
    public static FeedRootFragment feedRootFragment;

    public static WhereMainFragment whereMainFragment;
    public static FeedMainFragment feedMainFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
.....
        whereRootFragment=new WhereRootFragment();
        feedRootFragment=new FeedRootFragment();

        whereMainFragment=new WhereMainFragment();
        feedMainFragment=new FeedMainFragment();

        ClickHandler.handleClick(MainActivity.this, llWhere);
}

When tab button was clicked, it replaces old fragment with current fragment(handleClick method).

        switch (tag) {
        case TAG_WHERE:
            MainActivity.ivWhere.setImageDrawable(a.getResources().getDrawable(
                    R.drawable.where_black));
//          Fragment fragment_where_root=new WhereRootFragment();
            FragmentTransaction transaction_where = ((FragmentActivity) a).getSupportFragmentManager().beginTransaction();
            transaction_where.replace(R.id.root_frame, MainActivity.whereRootFragment);
            transaction_where.addToBackStack(null);
            transaction_where.commit();
            break;
        case TAG_FEED:
            MainActivity.ivFeed.setImageDrawable(a.getResources().getDrawable(
                    R.drawable.feed_black));
//          Fragment fragment_feed_root=new FeedRootFragment();
            FragmentTransaction transaction_feed = ((FragmentActivity) a).getSupportFragmentManager().beginTransaction();
            transaction_feed.replace(R.id.root_frame,  MainActivity.feedRootFragment);
            transaction_feed.addToBackStack(null);
            transaction_feed.commit();
            break;

WhereRootFragment:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    /* Inflate the layout for this fragment */
    View view = inflater.inflate(R.layout.fragment_where_root, container, false);

    FragmentTransaction transaction = getFragmentManager()
            .beginTransaction();
    transaction.replace(R.id.where_root_frame, MainActivity.whereMainFragment);
    transaction.addToBackStack(null);
    transaction.commit();

    return view;
}

WhereMainFragment

@Override
public View onCreateView(LayoutInflater inflater,
        @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_where_main,
            container, false);
    return rootView;
}

Result: enter image description here

[StartApp]->[1.Where:showing]->[2.Feed:showing]->[3.Where:it is not showing]->[4.Feed: showing saved state]->[5.Another fragment: it is empty as supposed]->[6.Feed:not showing]

Question: how to solve this problem? how to make fragment save its state?

Joe Rakhimov
  • 4,713
  • 9
  • 51
  • 109

2 Answers2

1

WhereRootFragment is managed by fragment manager belonging to the activity. The issue is happening because same fragment manager is being used to manage WhereMainFragment which is a child of WhereRootFragment.

WhereMainFragment should be managed by the fragment manager belonging to WhereRootFragment. To get child fragment manager in a fragment, make use of Fragment.getChildFragmentManager.

WhereRootFragment

public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    /* Inflate the layout for this fragment */
    View view = inflater.inflate(R.layout.fragment_where_root, container, false);

    // Use child fragment manager to manage WhereMainFragment
    FragmentTransaction transaction = getChildFragmentManager()
            .beginTransaction();
    transaction.replace(R.id.where_root_frame, MainActivity.whereMainFragment);
    transaction.addToBackStack(null);
    transaction.commit();

    return view;
}
Manish Mulimani
  • 17,535
  • 2
  • 41
  • 60
0

Some links are there that may useful to you:

-> You may have to use FragmentTabHost | Android Developers

-> Creating-and-Using-Fragments

-> you may want this Android Fragments

-> Best one Android Beginner

Stackoverflow Answer says:

public final class MyFragment extends Fragment {
    private TextView vstup;
    private Bundle savedState = null;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.whatever, null);
        vstup = (TextView)v.findViewById(R.id.whatever);

        /* (...) */

        /* If the Fragment was destroyed inbetween (screen rotation), we need to recover the savedState first */
        /* However, if it was not, it stays in the instance from the last onDestroyView() and we don't want to overwrite it */
        if(savedInstanceState != null && savedState == null)
            savedState = savedInstanceState.getBundle(App.STAV);
        if(savedState != null)
            vstup.setText(savedState.getCharSequence(App.VSTUP));
        savedState = null;

        return v;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        savedState = saveState(); /* vstup defined here for sure */
        vstup = null;
    }

    private Bundle saveState() { /* called either from onDestroyView() or onSaveInstanceState() */
        Bundle state = new Bundle();
        state.putCharSequence(App.VSTUP, vstup.getText());
        return state;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        /* If onDestroyView() is called first, we can use the previously savedState but we can't call saveState() anymore */
        /* If onSaveInstanceState() is called first, we don't have savedState, so we need to call saveState() */
        /* => (?:) operator inevitable! */
        outState.putBundle(App.STAV, savedState != null ? savedState : saveState());
    }

    /* (...) */

}
Community
  • 1
  • 1
Pratik Butani
  • 60,504
  • 58
  • 273
  • 437
  • Thank you for your answer, but this way is not suitable for me. Because each fragment will contain many views, inside other fragments. Is there any way to handle this automatically without restoring each views's state? – Joe Rakhimov Aug 29 '14 at 05:19