Save state in NavigationView

I am working with a new NavigationView trying to implement it in DrawerLayout and I want to keep the currently selected menu item in the NavigationView menu. I know that I can save / restore the selected item "manually" by saving / restoring the state of my instance:

public class MyActivity extends AppCompatActivity {
    private static String STATE_SELECTED_POSITION = "state_selected_position";
    private int mCurrentSelectedPosition;

    private NavigationView mNavigationView;
    private FrameLayout mContentFrame;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mNavigationView = (NavigationView) findViewById(R.id.navigation_view);
        mContentFrame = (FrameLayout) findViewById(R.id.content_frame);

        mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(MenuItem menuItem) {
                menuItem.setChecked(true);

                switch(menuItem.getItemId()) {
                    case R.id.navigation_item_1:
                        Snackbar.make(contentFrame, "Item One", Snackbar.LENGTH_SHORT).show();
                        mCurrentSelectedPosition = 0;
                        return true;
                    case R.id.navigation_item_2:
                        Snackbar.make(contentFrame, "Item Two", Snackbar.LENGTH_SHORT).show();
                        mCurrentSelectedPosition = 1;
                        return true;
                    default:
                        return false;
                }
            }
        });
    }

    // Saving the currently selected menu item (index).
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(STATE_SELECTED_POSITION, mCurrentSelectedPosition);
    }

    // Restoring selected menu item.
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION, 0);
        mNavigationView.getMenu().getItem(mCurrentSelectedPosition).setChecked(true);
    }

}

      

I stumbled upon NavigationView.SavedState hoping this would be the best solution, but I am having a hard time figuring out how to implement this into my activity. Anyone can help me figure out how to implement this? Thank.

+3


source to share


1 answer


: as of 22.2.1 in the support library the issue has been fixed and there is no more need to save / restore view state with the workaround mentioned below.


Do not use NavigationView.SavedState

NavigationView

is a view with saveEnabled

set to true. This means it SavedState

should be used internally by the view itself to automatically save / restore its state (ex: when rotating the device) Unfortunately the view has a confirmed error and the state is not saved / restored correctly: https://code.google.com/ p / android / issues / detail? id = 175224

here's a more general workaround for this problem:



public void onSaveInstance(Bundle outState) {
    ArrayList positions = findSelectedPosition();
    if(positions.size()>0) {
        outState.putIntegerArrayList(STATE_SELECTED_POSITION, positions);
    }
}

private ArrayList findSelectedPosition() {
    Menu menu = navDrawerFirstPart.getMenu();
    int count = menu.size();
    ArrayList result = new ArrayList<>();
    for (int i = 0; i < count; i++) {
        if(menu.getItem(i).isChecked()){
            result.add(i);
        }
    }
    return result;
}

public void onRestoreInstanceState(Bundle savedInstanceState) {
    if(savedInstanceState.containsKey(STATE_SELECTED_POSITION)){
        restoreSelectedPosition(savedInstanceState.getIntegerArrayList(STATE_SELECTED_POSITION));
    }
}

private void restoreSelectedPosition(ArrayList<Integer> positions) {
    Menu menu = navDrawerFirstPart.getMenu();
    for(int i=0; i<positions.size(); i++){
        menu.getItem(positions.get(i)).setChecked(true);
    }
}

      

Usage NavigationView.SavedState

will not be beneficial for this solution, since the state stored in it is a simple package that NavigationView

stores SparseBooleanArray

check states from items. Also, the function that starts the whole process of saving the instance internally NavigationView

is:

protected Parcelable onSaveInstanceState() {
    Parcelable superState = super.onSaveInstanceState();
    NavigationView.SavedState state = new NavigationView.SavedState(superState);
    state.menuState = new Bundle();
    this.mMenu.savePresenterStates(state.menuState);
    return state;
}

      

note which savePresenterStates

is part of the inner class MenuBuider

: is public, so it is visible, but again, since it is an inner class, should not be accessed outside of the support library package. And besides, the package that comes out of this function is wrong because that is the root of the problem.

+4


source







All Articles