Xamarin Android Menu item not show dynamically

Issue

I am working on on my app with Xamarin Android and I am having an issue with menu items. Problem appeared with update of Android libraries – all legacy support is now in AndroidX libraries so I migrated the whole project to it and following happened.

User off my application should be able to login. After login and register buttons hide and logout buttons shows. This works well but I found out it is just because of pop up login/register dialog, which somehow force the menu to redraw when the dialog closes. Problem is when user logouts, then respectively should login and register button show and logout button hide but only logout hides and other buttons don’t show. Only after clicking to something in the menu it redraw itself and button are shown.

It is all shown on screenshots.

Menu how it looks

login popup dialog

after login

after logout – buttons not shown

There are how I manipulate buttons:

private void SetupGuiAfterSignIn()
    {
        if (!User.IsSignIn())
            return;

        var navheadr  navigationView.GetHeaderView(0).FindViewById<LinearLayout>(Resource.Id.navheader);
        navheadr.Visibility  ViewStates.Visible;

        var navheaderUsername  navigationView.GetHeaderView(0).FindViewById<TextView>(Resource.Id.navheader_username);
        navheaderUsername.Text  User.GetEmail();

        navigationView.Menu.FindItem(Resource.Id.nav_login).SetVisible(false);
        navigationView.Menu.FindItem(Resource.Id.nav_register).SetVisible(false);
        navigationView.Menu.FindItem(Resource.Id.nav_logout).SetVisible(true);

        navigationView.Menu.FindItem(Resource.Id.nav_find_users).SetVisible(true);

        InvalidateOptionsMenu();

    }

private void SetupGuiAfterLogout()
    {
        if (User.IsSignIn())
            return;

        var navheadr  navigationView.GetHeaderView(0).FindViewById<LinearLayout>(Resource.Id.navheader);
        navheadr.Visibility  ViewStates.Gone;

        navigationView.Menu.FindItem(Resource.Id.nav_login).SetVisible(true);
        navigationView.Menu.FindItem(Resource.Id.nav_register).SetVisible(true);
        navigationView.Menu.FindItem(Resource.Id.nav_logout).SetVisible(false);

        navigationView.Menu.FindItem(Resource.Id.nav_find_users).SetVisible(false);


        InvalidateOptionsMenu();

    }

I also have OnCreateOptionsMenu:

public override bool OnCreateOptionsMenu(IMenu menu)
    {
        navigationView.InflateMenu(Resource.Menu.menu); //Navigation Drawer Layout Menu Creation  
        navigationView.InflateHeaderView(Resource.Menu.NavMenuHeader);
        base.OnCreateOptionsMenu(menu);
        return true;
    }

Solution

For the code you provided, i think it caused by the Login, Register, LoginOut is not set in the same group like below.

    <menu
xmlns:android"http://schemas.android.com/apk/res/android">
<group android:checkableBehavior"single">
    <item
android:id"@+id/nav_home"
android:title"Home" />
    <item
android:id"@+id/nav_findusers"
android:visible"false"
android:title"FindUsers" />
    <item
android:id"@+id/nav_import"
android:title"Import" />
    <item
android:id"@+id/nav_FAQ"
android:title"FAQ" />
    <item
android:id"@+id/nav_report"
android:title"ReportBug" />

</group>
<item>
    <menu>
        <item
android:id"@+id/nav_Login"
android:title"Login" />
        <item
android:id"@+id/nav_register"
android:title"Register" />
        <item  android:visible"false"
android:id"@+id/nav_LoginOut" 
android:title"LoginOut" />

    </menu>
</item>
</menu>

Updated:

You could use two groups and set the id to show the dividing line.

<?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_home"
android:title"Home" />
    <item android:visible"false"
android:id"@+id/nav_findusers"
android:title"FindUsers" />
    <item
  android:id"@+id/nav_import"
android:title"Import" />
    <item
android:id"@+id/nav_FAQ"
android:title"FAQ" />
    <item
android:id"@+id/nav_report"
android:title"ReportBug" />

</group>
<group android:id"@+id/tt" android:checkableBehavior"single">
    <item
android:id"@+id/nav_Login"
android:title"Login" />
    <item
android:id"@+id/nav_register"
android:title"Register" />
    <item  android:visible"false"
android:id"@+id/nav_LoginOut"
android:title"LoginOut" />
</group>
</menu>

Menu how it looks:

enter image description here

After login:

enter image description here

After logout:

enter image description here

The code when the item clicked:

  void setupDrawerContent(NavigationView navigationView)
    {
        navigationView.NavigationItemSelected + (sender, e) >
        {

            switch (e.MenuItem.ItemId)
            {
                case Resource.Id.nav_home:
                    {
                        //drawerLayout.OpenDrawer(Resource.Layout.Home);
                        //var home  new Intent(this, typeof(Activity_Home));
                        //StartActivity(home);
                        //navigationView.Menu.FindItem(Resource.Id.nav_LoginOut).SetVisible(true);
                        break;
                    }

                case Resource.Id.nav_Login:
                    {
                        navigationView.Menu.FindItem(Resource.Id.nav_LoginOut).SetVisible(true);
                        navigationView.Menu.FindItem(Resource.Id.nav_findusers).SetVisible(true);
                        navigationView.Menu.FindItem(Resource.Id.nav_Login).SetVisible(false);
                        navigationView.Menu.FindItem(Resource.Id.nav_register).SetVisible(false);


                        break;
                    }

                case Resource.Id.nav_LoginOut:
                    {
                        navigationView.Menu.FindItem(Resource.Id.nav_Login).SetVisible(true);
                        navigationView.Menu.FindItem(Resource.Id.nav_register).SetVisible(true);
                        navigationView.Menu.FindItem(Resource.Id.nav_LoginOut).SetVisible(false);

                        navigationView.Menu.FindItem(Resource.Id.nav_findusers).SetVisible(false);
                        break;
                    }

                default:
                    break;

                    //TODO check the ID and start your activity or switch the fragments
            }

            //e.MenuItem.SetChecked(true);
            //drawerLayout.CloseDrawers();
        };
    }

Answered By – Wendy Zang – MSFT

Leave a Comment