Search code examples
androidsavestateandroid-optionsmenu

How to save instance state of selected radiobutton on menu


I have options menu in my toolbar with radibutton item :

 <item
    android:id="@+id/map_menu"
    android:icon="@drawable/ic_layer"
    android:orderInCategory="102"
    app:showAsAction="always"
    android:title="@string/action_settings">
    <menu>
        <group
            android:id="@+id/map_types_group"
            android:checkableBehavior="single" >
            <item
                android:id="@+id/map_terrain"
                android:orderInCategory="1"
                app:showAsAction="ifRoom"
                android:title="@string/map_terrain"/>
            <item
                android:id="@+id/map_normal"
                android:orderInCategory="2"
                android:checked="true"
                app:showAsAction="ifRoom"
                android:title="@string/map_normal"/>
            <item
                android:id="@+id/map_hybrid"
                android:orderInCategory="3"
                app:showAsAction="ifRoom"
                android:title="@string/map_hybrid"/>
        </group>
    </menu>
</item>

I want to restore selected radiobutton when orientation change happened in onSaveInstanceState,onRestoreInstanceState but i can't understand how to get selected button from radiogroup in options menu.


Solution

  • Here is a fully working and tested example. With this code in place, no matter how many times you rotate the screen, the currently selected item will persist.

    First, create these instance variables to keep track of the state of the menu and have a name for the preference you will be saving in the Bundle:

    private final static String MENU_SELECTED = "selected";
    private int selected = -1;
    MenuItem menuItem;
    

    The saveInstanceState() method should save off the currently selected value:

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        savedInstanceState.putInt(MENU_SELECTED, selected);
        super.onSaveInstanceState(savedInstanceState);
    }
    

    Update the currently selected item in onOptionsItemSelected():

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    
        int id = item.getItemId();
    
        if (id == R.id.action_settings) {
            Log.d("settings", "id: " + id);
            return true;
        }
    
        if (id == R.id.map_terrain){
            Log.d("menuitem", "terrain id: " + id);
            selected = id;
            item.setChecked(true);
            return true;
        }
    
        if (id == R.id.map_normal){
            Log.d("menuitem", "normal id: " + id);
            selected = id;
            item.setChecked(true);
            return true;
        }
    
        if (id == R.id.map_hybrid){
            Log.d("menuitem", "hybrid id: " + id);
            selected = id;
            item.setChecked(true);
            return true;
        }
    
        return super.onOptionsItemSelected(item);
    }
    

    In onCreate(), load the saved data if it exists:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        if (savedInstanceState != null){
            selected = savedInstanceState.getInt(MENU_SELECTED);
        }
    }
    

    And then re-select the previously selected item in onCreateOptionsMenu():

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
    
        if (selected == -1){
            return true;
        }
    
        switch (selected){
            case R.id.map_terrain:
                menuItem = (MenuItem) menu.findItem(R.id.map_terrain);
                menuItem.setChecked(true);
                break;
    
            case R.id.map_normal:
                menuItem = (MenuItem) menu.findItem(R.id.map_normal);
                menuItem.setChecked(true);
                break;
    
            case R.id.map_hybrid:
                menuItem = (MenuItem) menu.findItem(R.id.map_hybrid);
                menuItem.setChecked(true);
                break;
        }
    
        return true;
    }