Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Current Fragment and Save on onSaveInstanceState() Method For Screen Orientation

I have one Activity with multiple Fragments. I am also using actionbarSherlock for my tabs which also connected to fragments.

My Problem is when I am going to rotate the screen (that is portrait to landscape/vice-versa), my activity will be called again so it restarts my activity.

I want not to restart my activity but just restore the current fragment that was shown before it was rotate. PLEASE don't answer android:configChanges="orientation|keyboardHidden" since it does not solved the issue but just like a simple hack of it. My solution was the OnsaveInstanceState and onRestoreInstanceState Methods but I just don't know how to use it with my problem. Please help me with this one. Any response are highly much appreciated.

CODE:

 public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    ActionBar actionBar = getSupportActionBar();  
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    ActionBar.Tab tabA = actionBar.newTab().setIcon(R.drawable.about);
    ActionBar.Tab tabE = actionBar.newTab().setIcon(R.drawable.faq);
    ActionBar.Tab tabB = actionBar.newTab().setIcon(R.drawable.sponsors);
    ActionBar.Tab tabC = actionBar.newTab().setIcon(R.drawable.map);
    ActionBar.Tab tabD = actionBar.newTab().setIcon(R.drawable.destination);
    Fragment aboutTab = new PhotosActivity();
    Fragment sponsorTab = new SongsActivity();
    Fragment mapTab = new HCCMapActivity(); 
    Fragment questTab = new FaqActivity(); 
    Fragment DestinationTab = new TourActivity();
    tabA.setTabListener(new MyTabsListener(aboutTab));
    tabB.setTabListener(new MyTabsListener(sponsorTab));
    tabC.setTabListener(new MyTabsListener(mapTab));
    tabD.setTabListener(new MyTabsListener(DestinationTab));
    tabE.setTabListener(new MyTabsListener(questTab));
    actionBar.addTab(tabD, 0, true);
    actionBar.addTab(tabC, 1, false);
    actionBar.addTab(tabA, 2, false);
    actionBar.addTab(tabB, 3, false);
    actionBar.addTab(tabE, 4, false);
}

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
  super.onSaveInstanceState(savedInstanceState);
  // Save UI state changes to the savedInstanceState.
  // This bundle will be passed to onCreate if the process is
  // killed and restarted.
  savedInstanceState.putString("MyString", "Welcome back to Android");
  //savedInstanceState.putString("id",)
  // etc.
  //getSupportFragmentManager().putFragment(savedInstanceState, "fragment", getSupportFragmentManager().findFragmentById(R.id.fragment_place));
}


@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
    FragmentManager fragmentManager ;
    FragmentTransaction ft ;
    super.onRestoreInstanceState(savedInstanceState);
  // Restore UI state from the savedInstanceState.
  // This bundle has also been passed to onCreate.
  String myString = savedInstanceState.getString("MyString");
  Log.i("Hello", myString);

    fragmentManager =  getSupportFragmentManager();
    ft = fragmentManager.beginTransaction();
    ft.setCustomAnimations(R.anim.slide_out_left, R.anim.slide_out_right);  
    ft.replace(R.id.fragment_place, getSupportFragmentManager().getFragment(savedInstanceState, "fragment"), null); 
}

@Override
public void onConfigurationChanged (Configuration newConfig){
    Log.i("hello", "Config");
    super.onConfigurationChanged(newConfig); 
}

@Override
public boolean onPrepareOptionsMenu (Menu menu) {
    //MenuItem menuitem1 = menu.findItem(R.id.menuitem1);
    //menuitem1.setVisible(false);

    menu.getItem(1).setVisible(false);
    menu.getItem(0).setVisible(false);
    return true;
}


 protected class MyTabsListener implements TabListener{

    Fragment fragment;

    public MyTabsListener(Fragment fragment){

        this.fragment = fragment;
    }

    public void onTabSelected(Tab tab, FragmentTransaction ft) {           
        if (myTabPosition < 0){
            //ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);  
        }else{
            if (myTabPosition >  tab.getPosition()){
                ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);   
            }else{
                ft.setCustomAnimations(R.anim.slide_out_left, R.anim.slide_out_right);  
            }
        }   
        myTabPosition = tab.getPosition();
        ft.replace(R.id.fragment_place, fragment, null);    
        //ft.commit();
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        // TODO Auto-generated method stub
        ft.remove(fragment);
        getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // TODO Auto-generated method stub

    }
}
like image 814
Junnel Gallemaso Avatar asked Sep 20 '12 13:09

Junnel Gallemaso


People also ask

What is the purpose of using onSaveInstanceState () here?

Basically, onSaveInstanceState is used for the scenario where Android kills off your activity to reclaim memory. In that scenario, the OS will keep a record of your activity's presence, in case the user returns to it, and it will then pass the Bundle from onSaveInstanceState to your onCreate method.

How do you save onSaveInstanceState?

1 Answer. Show activity on this post. You can replace above with the data you want to save and then re-populate your views like RecyclerView etc with the data you saved in the savedInstance as key-value pair. Just keep in mind that the Bundle is not meant to store Large amount of data.

How do you save a fragment state?

Various Android system operations can affect the state of your fragment. To ensure the user's state is saved, the Android framework automatically saves and restores the fragments and the back stack. Therefore, you need to ensure that any data in your fragment is saved and restored as well.


1 Answers

Fragments will be restored after a device rotation by default if you don't add them again. If you want the fragments to look the same then you should perform your onSaveInstanceState in the Fragment itself. In the Activity you could just do something like:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if(savedInstanceState == null) {
        /* First launch, add fragments */
    } else {
        /* 
           Activity restored, don't add new fragments or in your case,
           don't make the first tab selected. 
        */
    }
}

Even if you don't override onSaveInstanceState in the activity, the savedInstanceState parameter will still be non-null when restoring an Activity. It'll just be an empty Bundle.

Another option would be to store out what the selected tab index is and re-select that tab when your activity is restored.

@Override
public void onSaveInstanceState(Bundle outState) {
    outState.putInt("CurrentTab", currentTabIndex);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    /* Your existing code */

    if(savedInstanceState != null) {
        int currentTab = savedInstanceState.getInt("CurrentTab", 0);
        /* Set currently selected tab */
    }
}

This would re-select the current tab and show the Fragment that was being shown. The only downside to this is that your fragment's state isn't saved. To save the fragment's state, you'd have to do something like the first solution.

like image 183
Michael Celey Avatar answered Sep 29 '22 04:09

Michael Celey