Search code examples
javaandroidandroid-fragmentsandroid-actionbarandroid-architecture-navigation

Update ActionBar menu depending on navigation destination


I would like to change the menu items displayed in my ActionBar depending on the current destination of my NavController. By "change" I mean inflate a specified menu-xml for each destination.

The behavior could be compared to the integrated way the new navigation system changes the ActionBar title, depending on the given android:label for the destination fragment in the navigation-xml.

So far I setup a basic activity with ActionBar and DrawerLayout using the new Android navigation. Also I created all necessary XML files and Fragments to navigate between.

...

@Override
protected void onCreate(Bundle savedInstanceState)
{
    ...    

    this._drawerLayout = this.findViewById(R.id.drawer_layout);

    Toolbar toolbar = this.findViewById(R.id.action_bar);
    this.setSupportActionBar(toolbar);

    ActionBar actionbar = Objects.requireNonNull( this.getSupportActionBar() );
    actionbar.setDisplayHomeAsUpEnabled(true);
    actionbar.setHomeAsUpIndicator(R.drawable.ic_menu);

    NavigationView navigationView = this.findViewById(R.id.navigation_view);
    navigationView.setNavigationItemSelectedListener(menuItem -> {
        menuItem.setChecked(true);
        this._drawerLayout.closeDrawers();

        return true;
    });

    NavController navController = Navigation.findNavController(this, R.id.navigation_host);
    NavigationUI.setupWithNavController(toolbar, navController, this._drawerLayout);
}

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    // Here I inflate the ActionBar menu that is kept between all destinations.
    // Instead of keeping the same menu between all destinations I want to display different menus depending on the destination fragment.
    this.getMenuInflater().inflate(R.menu.actionbar_items, menu);

    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item)
{
    switch(item.getItemId())
    {
        case android.R.id.home:
            this._drawerLayout.openDrawer(GravityCompat.START);
            return true;
        case R.id.appbar_search:
            return true;
    }

    return super.onOptionsItemSelected(item);
}

I thought about using an individual toolbar in each destination fragment but I discarded the idea, because I would lose the transition animation between hamburger icon and back-arrow icon.

Is there any way to achieve this with the new navigation system or in any other way?


Solution

  • I found a way to achieve the desired behavior by calling menu.clear(); before inflating the updated layout. I am still wondering if there is a built-in way to achieve this with the new navigation system.

    In the destination Fragment I am using this now:

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
    {
        super.onCreateOptionsMenu(menu, inflater);
    
        menu.clear();
        inflater.inflate(R.menu.toolbar_items_idle, menu);
    }