Search code examples
c#androidxamarinxamarin.android

Xamarin Android Menu item not show dynamically


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