在按下后更新导航抽屉的选定状态

spa*_*ist 12 navigation android android-fragments navigation-drawer onbackpressed

什么是在按下后处理导航抽屉的选定状态的正确方法?

我有一个带有n个条目的导航抽屉(在列表视图中),就像Android Studio中的SDK示例一样.当我点击导航抽屉条目时,我希望它们被添加到后台堆栈,所以我可以回到它们.

在onNavigationDrawerItemSelected(int pos)我有

        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        if (position == 0) {
            transaction.replace(R.id.container, new FragmentA());
        } else if (position == 1) {
            transaction.replace(R.id.container, new FragmentB());
        } else {
            transaction.replace(R.id.container, new FragmentC());
        }
        transaction.addToBackStack(null);
        transaction.commit();
Run Code Online (Sandbox Code Playgroud)

当我点击抽屉中的第二个条目时,B被选中并替换A.如果我之后单击后退按钮,片段A将再次显示,但仍然在导航抽屉中选择了B.

如何在按下后更新抽屉的选择状态?

不知怎的,我需要调用mDrawerListView.setItemChecked(position,true); 或NavigationDrawerFragment.selectItem(int position).但到了哪个位置?我怎么记得呢?

拦截onBackPressed?

@Override
    public void onBackPressed() {}
Run Code Online (Sandbox Code Playgroud)

但我怎么知道哪个片段再次活跃?它对应于哪个位置.

有一些简单的解决方案我是盲目的看到的吗?似乎与导航抽屉结合使用并更新选择状态是标准模式.

mat*_*ash 8

"正确返回导航"文档的" 实现碎片的后退导航"部分中描述了此模式.

如果您的应用程序更新其他用户界面元素以反映片段的当前状态(例如操作栏),请记住在提交事务时更新UI.除了提交事务之外,您应该在后台堆栈更改后更新用户界面.您可以FragmentTransaction通过设置以下内容来监听 恢复时间 FragmentManager.OnBackStackChangedListener:

getSupportFragmentManager().addOnBackStackChangedListener(
    new FragmentManager.OnBackStackChangedListener() {
        public void onBackStackChanged() {
            // Update your UI here.
        }
    });
Run Code Online (Sandbox Code Playgroud)

这将是刷新导航抽屉中当前选项的适当位置.


小智 6

今天我也有同样的挣扎。我通过FragmentToActivity每个片段以及我唯一的MainActivity中实现一个接口来解决它。

接口:

public interface FragmentToActivity {
    public void SetNavState(int id);
}
Run Code Online (Sandbox Code Playgroud)

片段:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    ((FragmentToActivity) getActivity()).SetNavState(R.id.nav_myitemid); //just add this line
}
Run Code Online (Sandbox Code Playgroud)

主要活动:

@Override
public void SetNavState(int id) {
    NavigationView nav = (NavigationView) findViewById(R.id.nav_view);
    nav.setCheckedItem(id);
}
Run Code Online (Sandbox Code Playgroud)

如果您不知道它的R.id.nav_myitemid来源,这里是我的activity_main_drawer.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">    
    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_myitemid"
            android:title="@string/home" />
    </group>
</menu>
Run Code Online (Sandbox Code Playgroud)


小智 5

我试图找出这个问题的解决方案有很多麻烦,我最终使用的解决方案在我看来并不"好",但它确实有效.

在我的应用程序中,当我将片段添加到backstack时,我最终在导航抽屉中添加了片段位置.这样我可以使用onBackStackChanged()中的位置调用setItemChecked.基本上我做的是这样的:

@Override
public void onBackStackChanged() {
    FragmentManager fm = getFragmentManager();
    String name = fm.getBackStackEntryAt(fm.getBackStackEntryCount()-1).getName();
    mDrawerList.setItemChecked(Integer.parseInt(name),true);
}

public class DrawerItemClickListener implements android.widget.AdapterView.OnItemClickListener {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        selectItem(position);
    }
}

private void selectItem(int position) {
    Fragment fragment;

    switch (position) {
        case 0: // Home
            fragment = new ContentFragment();
            break;
        case 1: // Another
           fragment = new AnotherFragment();
            break;
        default: // Logout
        {
            finish();

            Intent intent = new Intent(this, StartupActivity.class);
            startActivity(intent);

            return;
        }
    }

    FragmentManager fragmentManager = getFragmentManager();
    fragmentManager.beginTransaction()
            .replace(R.id.content_frame, fragment)
            .addToBackStack(Integer.toString(position))
            .commit();

    mDrawerList.setItemChecked(position, true);
    setTitle(mNavigationItems[position]);
    mDrawerLayout.closeDrawer(mDrawerList);
}
Run Code Online (Sandbox Code Playgroud)