ActionBar Drop Down navigation - orientation change puts wrong fragment in
Asked Answered
B

1

6

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);
}

}

Beverlybevers answered 3/1, 2013 at 19:28 Comment(0)
C
2

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

Chiquia answered 16/1, 2013 at 3:34 Comment(3)
Hi, what I actually ended up doing was persisting the index of item selected in the dropdown in the savedinstanceBeverlybevers
I was doing this as well (actually I stored the index as a SharedPreference so that it could be used upon starting the app if it was opened at a later time when no longer running in memory). The problem I was facing is a little different in that the visible fragment could start another child fragment. On rotation it would then go back to the parent fragment instead of the child, the code above allowed me to work around that second issue.Chiquia
This causes the wrong fragment to be displayed in the drop down menu on the action bar.Lowery

© 2022 - 2024 — McMap. All rights reserved.