在片段返回堆栈中更改导航抽屉选定项

13

我有两个碎片FragmentHomeFragmentAbout,我在应用中添加了NavigationDrawer,当我点击Home时,它会打开FragmentHome,而About则会打开FragmentAbout,当我打开FragmentAbout时,我也将其添加到后退栈中。这很好地发挥了作用。

现在的问题是,当我点击About并按下返回按钮时,它会回到FragmentHome,但是NavigationDrawer仍然显示About作为选定项,我希望在从FragmentAbout按下返回按钮时,将此选定项更改为Home

主页 Activity:

public class ActivityHome extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {

Toolbar toolbar;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);

    // Toolbar
    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    // Drawer layout
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.nav_drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.nav_drawer_open, R.string.nav_drawer_close);
    assert drawer != null;
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    // Navigation view
    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    assert navigationView != null;
    navigationView.setNavigationItemSelectedListener(this);

    // Open first menu item
    navigationView.getMenu().performIdentifierAction(R.id.nav_home, 0);

    // Set first item checked
    navigationView.setCheckedItem(R.id.nav_home);
}

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {

    final MenuItem menuItem = item;

    // Check if menu item is selected
    if (item.isChecked())
        item.setChecked(false);
    else
        item.setChecked(true);

    // Handle navigation view item clicks here.
    int id = item.getItemId();

    if (id == R.id.nav_home) {

        // Open home fragment
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.frame_layout, new FragmentHome())
                .commit();

    } else if (id == R.id.nav_about) {

        toolbar.setTitle("About");

        // Open home fragment
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.frame_layout, new FragmentAbout())
                .addToBackStack(null)
                .commit();

    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.nav_drawer_layout);
    assert drawer != null;
    drawer.closeDrawer(GravityCompat.START);
    return true;
}

@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.nav_drawer_layout);
    assert drawer != null;
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else {
        super.onBackPressed();
    }
}}

主页碎片

public class FragmentHome extends Fragment {

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_home, container, false);
}

@Override
public void onResume() {
    super.onResume();
    ((AppCompatActivity)getActivity()).getSupportActionBar().setTitle(R.string.fragment_home_title);
}
}

FragmentAbout 的代码与 FragmentHome 相同,只是布局不同。

我在stackoverflow上搜索了很多,但尚未找到任何解决方案,所以如果有人知道如何做,请告诉我。


导航抽屉仍然显示“关于”作为选定项...你是在说工具栏标题吗??? - Saurabh Vardani
@Saurabh 不是工具栏标题,工具栏标题正常工作,我想将抽屉中高亮的菜单项更改为“主页”。 - Darpan Kulkarni
你找到了吗? - Venkat Ramana
3个回答

15

有一个OnBackStackChangedListener可以用来实现此功能。我尝试了一下,效果很好。

public Fragment getCurrentFragment() {
    return this.getSupportFragmentManager().findFragmentById(R.id.fragment_container);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
   ...
   this.getSupportFragmentManager().addOnBackStackChangedListener(
       new FragmentManager.OnBackStackChangedListener() {
          public void onBackStackChanged() {
              Fragment current = getCurrentFragment();
              if (current instanceof MyFragmentA) {
                 navigationView.setCheckedItem(R.id.nav_myfragA);
              } else {
                 navigationView.setCheckedItem(R.id.nav_myfragB);
           }
       }
   });
...
}

这种方法是可行的,但如果您将相同的片段用于不同的项目,则会出现错误。此外,如果您打开一个 DialogFragment(而不是 fragment)并关闭它,则不会调用此事件。 - CoolMind
@CoolMind 对于相同的代码片段,您可以比较标签。 - Amir

0

这可能不是一个好的解决方案,但至少对我来说是可以接受的。每当从导航抽屉中点击片段菜单时,您需要将片段位置存储在堆栈变量(例如:List)中。然后重写 onBackPressed 方法以从堆栈中删除最后一个值,并将抽屉位置设置为堆栈的当前最后一个值。以下是示例:

private List<Integer> itemPositionStacks = new ArrayList<>();

protected void onCreate(@Nullable Bundle savedInstanceState) {
    itemPositionStacks.add(currentSelectedPosition);
}

public void onNavigationViewItemSelected(int itemId) {
        Fragment fr = null;
        switch (itemId) {
            case 0:
                fr = new aFragment();
                break;
            case 1:
                fr = new bFragment();
                break;
        }

        getSupportFragmentManager().beginTransaction()
                .replace(R.id.container, fr)
                .addToBackStack(null)
                .commit();

        Drawer.getInstance().setDrawerChecked(itemId);
        itemPositionStacks.add(itemId);
    }

public void onBackPressed() {
        if(itemPositionStacks.size() > 1) {
            itemPositionStacks.remove(itemPositionStacks.size() - 1);
            Drawer.getInstance().setDrawerChecked(itemIdStacks.get(itemIdStacks.size() - 1));
        }
        super.onBackPressed();
    }

-2
在你的onBackPressed()函数中,你必须通过使用来选择哪个项目被选中。
drawer.setCheckedItem(R.id.nav_home);

并取消另一项的选择

drawer.getMenu().findItem(R.id.nav_about).setChecked(false);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接