Learning Xamarin–Menus!

By October 30, 2013Uncategorized
[Please see the Table of Contents for this series.]

In this entry, I look at creating menus in an Android application.

Menu1In my last post in this series, I looked at how to pass data from one Activity to another using JSON.  We’ll build on that example in this one, both to have a nice starter app and also to pass the menu choice along within the View Model. 

To get started, make a copy of the previous application (you can download it here).  Now we are going to override two methods in the first activity to create the menus and to respond to menu choices, and then we’re going to modify the VM a bit to make it easier to transfer the menu choice to the second Activity.

To begin, open FirstActivity.cs.  The bulk of our interesting work is in the override of OnCreateOptionsMenu:

public override bool OnCreateOptionsMenu(IMenu menu)
{
//…
}

Our first job is to chain up to the base implementation

public override bool OnCreateOptionsMenu(IMenu menu)
{
base.OnCreateOptionsMenu(menu);
}

We next create a few counters that will be used for organizing and uniquely identifying the menu items,

int groupId = 0;
int menuItemId = Android.Views.Menu.First;
int menuItemOrder = Android.Views.Menu.None;

We are now ready to create our first menu item.  We’ll create its name as a variable, and then plug the various values into the Add method on the IMenu object that was passed in as a variable,

var menuName = "Options";
menu.Add(groupId, menuItemId, menuItemOrder, menuName);

We can add a couple more menu items in much the same way,

menu.Add(groupId, menuItemId + 1, menuItemOrder + 1, "Thing 1");
menu.Add(groupId, menuItemId + 2, menuItemOrder + 2, "Thing 2");

Notice that although they all share the same groupId, they must (and do) have unique menuItemId values and menuItemOrder values (the latter dictates their relative placement).

Menu2Let’s add a sub-menu.  Sub-menus let you extend your menu creating a hierarchy of choices and reducing the cognitive load on your users.  In this case, we’ll add an icon for the menu item and an icon for the header of the sub-menu (as shown in the figure)

ISubMenu sub = menu.AddSubMenu(
groupId,
menuItemOrder + 3,
menuItemOrder + 3,
"Android");
sub.SetHeaderIcon(Resource.Drawable.Icon);
sub.SetIcon(Resource.Drawable.Icon);

 

Finally, we add the sub menus, much as we do the menu items.  On the second sub-menu we’ll add a checkbox by adding the SetCheckable method and passing in true.  We return true from the entire method,

sub.Add(groupId, menuItemId + 4, menuItemOrder + 4, "Native?");

sub.Add(groupId, menuItemId + 5, menuItemOrder + 5,
"Xamarin!").SetCheckable(true);

return true;
}

Handling the Menu Choice

To respond to the menu choice we need to override OnMenuItemSelected,

public override bool OnMenuItemSelected(
int featureId, IMenuItem item)
{
vm.MenuChoice = item.ItemId.ToString();
return true;
}

As you can see, we receive the item, an IMenuItem object, as a parameter.  We can reach into that object and pluck out the ItemId of the selected menu item, and in this case we assign it to a new property in our ViewModel, MenuChoice.  To do so, we need to update the ViewModel,

class MyViewModel
{
public string Name { get; set; }
public string State { get; set; }
public string MenuChoice { get; set; }
}

and, you need to move the ViewModel to be a private member variable of your FirstActivity,

public class FirstActivity : Activity
{
private MyViewModel vm;

In this case, you will need to initialize the vm in the OnCreate method,

protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
vm = new MyViewModel();

Finally, you’ll modify the ButtonClicked event handler to fill in the values for name and state,

private void ButtonClicked(object sender, EventArgs e)
{
// var vm = new MyViewModel()
// { Name = "Jesse Liberty", State = "MA"};

vm.Name = "Jesse Liberty";
vm.State = "MA";

Displaying the Result

To display the menu choice on the second Activity, you’ll modify both Layout/Second.axml and SecondActivity.cs, but there is nothing surprising or new here.  In Second.axml just add the third TextView,

<TextView
android:id="@+id/Text3"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

And in SecondActivity.cs you’ll get a reference to text3 and populate it,

var text3 = FindViewById<TextView>(Resource.Id.Text3);
//…
text3.Text = "Menu choice: " + vm.MenuChoice;

That’s all it takes to create and use a menu in Android by way of Xamarin.  Piece of cake.

About the Author

JesseJesse Liberty is a Master Consultant for Falafel Software, a Microsoft MVP, an author,  and he creates courses forPluralsight.    Liberty hosts the popular Yet Another Podcast and his blog is considered required reading. He was a Senior Evangelist for Microsoft,  a XAML Evangelist for Telerik, a Distinguished Software Engineer at AT&T; Software Architect for PBS and Vice President of Information Technology at Citibank. Jesse can be followed on twitter at @JesseLiberty

The following two tabs change content below.