Contextual Actions for List Items

Rather than in-cell controls I want to use item-based context actions to allow the buying of items on the Buy page and the adding of items to the Buy page from the Add page.

IMG_0999

Xamarin.Forms supports these contextual actions–on iOS they’re rendered as a left swipe on a row and on Android they’re revealed by a long-press on a row (I know my design calls for left and right swipes but let’s work with what the platform provides out-of-the-box right now).

To do this I created a new Cell class that inherits from TextCell, created some new MenuItems and added them to the ContextActions collection for the cell. Here’s the BuyCell code for BuyPage.

internal class BuyCell : TextCell
{
	public BuyCell()
	{
		var boughtAction = new MenuItem { Text = "Bought", IsDestructive = true };
		var plusOneAction = new MenuItem { Text = "+1" };

		ContextActions.Add(boughtAction);
		ContextActions.Add(plusOneAction);
	}
}

The text of the MenuItem is specified in the Text property. The IsDestructive property indicates whether or not the menu item will remove it’s respective UI element from the ListView and, when true, the item is rendered differently from the other MenuItems (on iOS it’s drawn with a red background). There’s also a Clicked event that’s raised when the MenuItem is tapped but I haven’t specified that yet.

One by one the MenuItems are added to the ContextActions collection. It appears that if none of the MenuItem’s IsDestructive properties are set to true the items are added in right-to-left order. However, if a MenuItem’s IsDestructive property is set to true, it appears to always be on the far right (it’s recommended that only one MenuItem in a cell’s ContextActions collection have its IsDestructive property be set to true but you can break that rule).

In the figure below the actions in red have their IsDestructive property set to true and you can see how it affects the ordering of items.

Viand-ContextActions-Add-Order-A

The next step is to replace the old occurrence’s of TextCell when the BuyPage ListView is created and its TextProperty is bound to one of the Item properties.

buyView = new ListView {
	RowHeight = 60,
	ItemsSource = buyItems,
	ItemTemplate = new DataTemplate(typeof(BuyCell))
};

buyView.ItemTemplate.SetBinding(BuyCell.TextProperty, "Name");

Here’s to corresponding code for AddPage.

// AddPage's AddCell
internal class AddCell : TextCell
{
	public AddCell()
	{
		var buyAction = new MenuItem { Text = "Buy" };
		var removeAction = new MenuItem { Text = "Remove", IsDestructive = true };

		ContextActions.Add(removeAction);
		ContextActions.Add(buyAction);
	}
}

// Using AddCell when creating the AddPage ListView and doing data binding
addView = new ListView {
	RowHeight = 60,
	ItemsSource = addItems,
	ItemTemplate = new DataTemplate(typeof(AddCell))
};

addView.ItemTemplate.SetBinding(AddCell.TextProperty, "Name");

I still have to add the appropriate method calls to each MenuItem’s Clicked event so tapping on each MenuItem calls the appropriate code.

  • +1 – Visibly increment the quantity (so if the item is “Milk” tapping “+1” will change the display to “Milk (2)”
  • Bought – Removes the item from the Buy list and adds it to the Add list
  • Buy – Removes the item from the Add list and adds it to the Buy list
  • Remove – Removes the item permanently from the Add list

IMG_0999

And just to remind you that all of this work is cross-platform, here are the same context actions rendered on Android without any changes to the code above.

IMG_0999-Android

This entry was posted in Side Projects, Software Development and tagged , , , , . Bookmark the permalink.

One Response to Contextual Actions for List Items

  1. Pingback: Hooking Up Contextual Actions to Methods | Objective.Me

Comments are closed.