Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ActionBar Drop Down navigation - orientation change puts wrong fragment in

I am having a actionbar dropdown navigation. The problem is when I switch to a different fragment, then do an orientation change, it puts the first fragment inside anyways, even though I think I am handing savedInstanceState correctly. The problem seems to be that onNavigationItemSelected gets called, so .. how would I correctly handle this? I could make the savedInstanceState variable a field, but that just feels wrong...

public class MainActivity extends FragmentActivity implements MyListFragment.OnArticleSelectedListener {

public static final String TAG = "MainActivity";

@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if(savedInstanceState != null) {
        Fragment savedFragment = getSupportFragmentManager().getFragment(savedInstanceState, "saved_fragment");
        Log.d(MainActivity.TAG, "savedInstanceState != null: " + savedFragment.getTag());

        getSupportFragmentManager()
        .beginTransaction()
        .replace(R.id.fragment_container, savedFragment, savedFragment.getTag())
        .commit();
    } else {

        Log.d(MainActivity.TAG, "savedInstanceState == null");

        getSupportFragmentManager()
        .beginTransaction()
        .replace(R.id.fragment_container, new MyListFragment(), MyListFragment.TAG)
        .commit();
    }

    ActionBar actionBar = getActionBar();
    actionBar.setDisplayShowTitleEnabled(false);
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);

    String[] array = new String[] { "Inzeráty", "Dummy frag" };
    SpinnerAdapter mSpinnerAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item,
            array);

    actionBar.setListNavigationCallbacks(mSpinnerAdapter, new ActionBar.OnNavigationListener() {

        @Override
        public boolean onNavigationItemSelected(int itemPosition, long itemId) {

            Log.d(MainActivity.TAG, "onNavitagionItemSelected");

            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            switch(itemPosition) {
                case 0: 
                    transaction.replace(R.id.fragment_container, new MyListFragment(), MyListFragment.TAG);
                    break;
                case 1:
                    transaction.replace(R.id.fragment_container, new MyDummyFragment(), MyDummyFragment.TAG);
                    break;
            }
            transaction.commit();
            return true;
        }

    });

}

@Override
public void onArticleSelected(Bundle bundle) {
    Log.d(MainActivity.TAG, "MainActivity # onArticleSelected");
    Intent intent = new Intent(this, DetailActivity.class);
    intent.putExtras(bundle);
    startActivity(intent);
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
    Log.d(MainActivity.TAG, "MainActivity # onSaveInstanceState: " + currentFragment.getTag());
    getSupportFragmentManager().putFragment(outState, "saved_fragment", currentFragment);
    super.onSaveInstanceState(outState);
}

}

like image 562
urSus Avatar asked Jan 03 '13 19:01

urSus


1 Answers

I recently encountered this problem as well. I addressed it by overriding the onRetainCustomNonConfigurationInstance method on the activity.

@Override
public Object onRetainCustomNonConfigurationInstance() {
    // return true so that onCreate will know it is an orientation change
    return true;
}

In my onCreate I was then able to implement the following:

...
Object lastCustomNonConfigurationInstance = getLastCustomNonConfigurationInstance();
if (lastCustomNonConfigurationInstance != null) {
    mIsOrientationChange = (Boolean) getLastCustomNonConfigurationInstance();
}
...

Lastly I updated onNavigationItemSelected so that it knew about mIsOrientationChange

 @Override
public boolean onNavigationItemSelected(int position, long id) {
    if (!mIsOrientationChange) {
        // real navigation selected logic           
    }

    mIsOrientationChange= false;

    return true;
}

Edit: I got the idea to implement this from the following Android Developer article: http://developer.android.com/guide/topics/resources/runtime-changes.html#RetainingAnObject

like image 77
Mike Schreiner Avatar answered Sep 28 '22 06:09

Mike Schreiner