How to keep the same fragment when activity restarts due to orientation change in a Navigation Drawer Activity
Asked Answered
D

3

6

I found many post explaining how get the Fragment from the savedInstanceState Bundle but, because the Activity can swap between 4 Fragments, i need a way to know which Fragment was alive before rotate when the orientation started to change.

The reason i have several Fragments is because i am using Navigation Drawer, so each menu item as a fragment.

Disburse answered 20/1, 2017 at 20:10 Comment(2)
I found many post explaining how get the Fragment from the savedInstanceState Bundle - really? In an Activity you can call isChangingConfigurations() method AFTER onPause() to find out if a configuration change is occurring or not. Not exactly what you're after, but this will return true if a configuration change is happening, and false if not i.e. Activity is being destroyed and not recreated.Overshoe
When an orientation change happens, the system takes care of displaying the Fragments to the state how it was in the previous activity, i.e. your activity gets destroyed, but not your FragmentManager. As soon as your new activity gets created, it will take care of adding those fragment to this newly created activity. What issue do you have exactly?Lunchroom
D
-1

Found my own answer and it it was a really simple thing after all. I left the solution here for those who are not familiar to android,like me .

//current fragment
int fragment_id;

//make fragment selection available form the menu resource id
private void setFragment(MenuItem item) {

    Fragment fragment = null;
    fragment_id = item.getItemId();

    switch (fragment_id) {
        case R.id.nav_option_1:
            fragment = MyFragment1.newInstance(true);
            break;
        ...
        //Set fragment
        FragmentTransaction t = getSupportFragmentManager().beginTransaction();
        t.replace(R.id.content_navigation, fragment);
        t.commit();
    }

    item.setChecked(true);
}

private class DrawerItemClickListener implements NavigationView.OnNavigationItemSelectedListener {

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        setFragment(item);
        return false;
    }
}

//save the state
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt(SAVE_INSTANCE_FRAGMENT_KEY, fragmentid);
}

//restore the saved fragment on create
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_navigation);
    ///...
    if (savedInstanceState != null) {
        int fragment_id = savedInstanceState.getInt(SAVE_INSTANCE_FRAGMENT_KEY);
        selectItem(mDrawerList.getMenu().findItem(fragment_id));
    } else {
        selectItem(mDrawerList.getMenu().findItem(R.id.home_fragment_id));
    }

}
Disburse answered 28/1, 2017 at 12:2 Comment(0)
F
7

I had the same issue and I fixed it adding this to the Navigation Drawer activity code:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if(savedInstanceState==null){
        //Handle the initial fragment transaction
    }
    ...
}

For example, I have a navigation drawer with "Home", "Settings" and "About" as menu items, each with a fragment "home_fragment", "settings_fragment" and "about_fragment".

If I want "home_fragment" to appear when the navigation drawer activity launches, I use this code on the OnCreate function:

FragmentManager fM = getSupportFragmentManager();
fM.beginTransaction().replace(R.id.NavDrawContent,new home_fragment()).commit();

But I want it to execute only when (savedInstanceState == null), so that when we change the phone orientation while in settings_fragment (for example), it doesn't inflate home_fragment.

So the final code (inside the navigation drawer activity OnCreate):

super.onCreate(savedInstanceState);
if(savedInstanceState==null){
    FragmentManager fM = getSupportFragmentManager();
    fM.beginTransaction().replace(R.id.NavDrawContent,new home_fragment()).commit();
}
Full answered 5/9, 2017 at 16:41 Comment(0)
C
3

In the activity, you save the fragment's instance in onSaveInstanceState() and restore in onCreate().

@Override
public void onCreate(Bundle savedInstanceState) {
    ...
    if (savedInstanceState != null) {     
        fragment = getSupportFragmentManager().getFragment(savedInstanceState, "KEY");
        changeFragment(fragment, "MY TAG")
    } else {
        setupFragment();
    }
    ...
}


@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    Fragment fragment = getSupportFragmentManager().findFragmentByTag("MY TAG");
    if (fragment != null) {
        getSupportFragmentManager().putFragment(outState, "KEY", fragment);
    }
}

If you need to know which fragment was saved, you can check with instanceof, for example:

if (fragment instanceof SettingsFragment) {
    // ...
}
Cystotomy answered 20/1, 2017 at 20:54 Comment(2)
When onSaveInstanceState is called, what i need to save is the class of the fragment, or something that tells me what was the current fragment active. Navigation Drawer swap the fragments when the user select another option on the navigation menu.Disburse
You can use fragment.getClass().getSimpleName() to get the class name. outState.putString("CLASS", fragment.getClass().getSimpleName());Cystotomy
D
-1

Found my own answer and it it was a really simple thing after all. I left the solution here for those who are not familiar to android,like me .

//current fragment
int fragment_id;

//make fragment selection available form the menu resource id
private void setFragment(MenuItem item) {

    Fragment fragment = null;
    fragment_id = item.getItemId();

    switch (fragment_id) {
        case R.id.nav_option_1:
            fragment = MyFragment1.newInstance(true);
            break;
        ...
        //Set fragment
        FragmentTransaction t = getSupportFragmentManager().beginTransaction();
        t.replace(R.id.content_navigation, fragment);
        t.commit();
    }

    item.setChecked(true);
}

private class DrawerItemClickListener implements NavigationView.OnNavigationItemSelectedListener {

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        setFragment(item);
        return false;
    }
}

//save the state
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt(SAVE_INSTANCE_FRAGMENT_KEY, fragmentid);
}

//restore the saved fragment on create
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_navigation);
    ///...
    if (savedInstanceState != null) {
        int fragment_id = savedInstanceState.getInt(SAVE_INSTANCE_FRAGMENT_KEY);
        selectItem(mDrawerList.getMenu().findItem(fragment_id));
    } else {
        selectItem(mDrawerList.getMenu().findItem(R.id.home_fragment_id));
    }

}
Disburse answered 28/1, 2017 at 12:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.