在NavigationView上保存状态

时间:2015-06-02 09:22:12

标签: android

我正在使用新的NavigationView,尝试将其实现为DrawerLayout,并且我想在NavigationView中的菜单中保存当前选定的菜单项。 我知道我可以保存/恢复所选项目"手动"通过保存/恢复我的实例状态:

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

}

我偶然发现了NavigationView.SavedState,希望这是一个更好的解决方案,但我很难弄清楚如何将这个实现到我的活动中。 有谁可以帮我弄清楚如何实现这个?感谢。

1 个答案:

答案 0 :(得分:4)

更新:从支持库的22.2.1开始,问题已修复,不再需要使用下面提到的解决方法保存/恢复视图状态

不要使用NavigationView.SavedState

NavigationViewsaveEnabled设置为true的视图。 这意味着视图本身应在内部使用SavedState来自动保存/恢复其状态(例如:设备轮换时) 不幸的是,视图有一个确认的错误,状态未正确保存/恢复: https://code.google.com/p/android/issues/detail?id=175224

here您将找到针对该问题的更一般的解决方法:

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

使用NavigationView.SavedState对此解决方案没有任何优势,因为状态 存储在其中的,它是一个简单的捆绑包,其中NavigationView存储来自项目的检查状态的SparseBooleanArray。 除此之外,启动NavigationView内部实例保存的所有过程的函数是:

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

请注意savePresenterStates是内部类MenuBuider的一部分:是公开的,因此它是可见的,但是因为它是内部类,所以不应该在包外访问的支持库。除此之外,来自该功能的捆绑包是错误的,因为它是问题的根源。