How to add UIContextMenuInteraction to button on Xamarin Forms?

Issue

I need to add a context menu to a button for Xamarin iOS. I found an example on the apple developer site.

So I need to do quite a similar context menu but it should be anchored to the button element.

I created control and named it InteractionButton

public class InteractionButton : Button
{
    public static readonly BindableProperty ButtonsListProperty  BindableProperty.Create(
        nameof(ButtonsList), typeof(List<string>), typeof(InteractionButton));

    public List<string> ItemsList
    {
        get > (List<string>) GetValue(ButtonsListProperty);
        set > SetValue(ButtonsListProperty, value);
    }
}

Also, I created a simple iOS renderer for the control –

[assembly: ExportRenderer(typeof(InteractionButton), typeof(InteractionButtonRenderer))]
public class InteractionButtonRenderer : ButtonRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
    {
        base.OnElementChanged(e);


        if (e.NewElement is InteractionButton button)
        {
            // create context menu from button.ItemsList
            // NativeView.AddInteraction(new UIContextMenuInteraction());
        }
    }
}

The problem is that I don’t know how should I build UIContextMenuInteraction. We should pass an instance of type IUIContextMenuInteractionDelegate into the UIContextMenuInteraction object. I could not find any examples of how to do it. All that I have is an example from the apple developer site:

let button  UIButton(type: .system)
button.setImage(UIImage(systemName: "plus"), for: .normal)

let barButton  UIBarButtonItem(customView: button)
self.navigationItem.rightBarButtonItem  barButton

let interaction  UIContextMenuInteraction(delegate: self)
button.addInteraction(interaction)


extension ViewController: UIContextMenuInteractionDelegate {
    func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) 
    -> UIContextMenuConfiguration? {
        return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { suggestedActions in
            let importAction  UIAction(title: "Import", image: UIImage(systemName: "folder")) { action in }
            let createAction  UIAction(title: "Create", image: UIImage(systemName: "square.and.pencil")) { action in }
            return UIMenu(title: "", children: [importAction, createAction])
        }
    }
}

Is there a simple way of adding context menu interaction to my native control?

Solution

I test with the following code it works fine , just long click on the button it will shows the menu .

InteractionButton

    public class InteractionButton : Button
    {
        public static readonly BindableProperty ItemsListProperty  BindableProperty.Create(
            nameof(ItemsList), 
            typeof(List<string>), 
            typeof(InteractionButton));

        public List<string> ItemsList
        {
            get > (List<string>)GetValue(ItemsListProperty);
            set > SetValue(ItemsListProperty, value);
        }
    }

Xaml

 <local:InteractionButton HeightRequest"100" WidthRequest"100" Text"Click on me" ItemsList"{Binding list}"/>

Custom renderer

[assembly: ExportRenderer(typeof(InteractionButton), typeof(MyRenderer))]
namespace FormsApp.iOS
{

    class MyRenderer : ButtonRenderer , IUIContextMenuInteractionDelegate
    {
        public UIContextMenuConfiguration GetConfigurationForMenu(UIContextMenuInteraction interaction, CGPoint location)
        {

            List<UIMenuElement> elementList  new List<UIMenuElement>();
            foreach (var item in (Element as InteractionButton).ItemsList) {

                UIAction action  UIAction.Create(item, UIImage.FromFile("dog.png"), item, (a) > {
                    Console.WriteLine("Click on action1");
                });

                elementList.Add(action);
            }
            UIMenu menu  UIMenu.Create("Menu", elementList.ToArray());
            return UIContextMenuConfiguration.Create(null,null,(suggestedActions) > menu);
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged(e);

            if (Control ! null)
            {

                var interaction  new UIContextMenuInteraction(this);
                Control.AddInteraction(interaction);
            }
        }
    }
}

enter image description here

Answered By – ColeX – MSFT

Leave a Comment