如何将 UIContextMenuInteraction 添加到 Xamarin Forms 上的按钮?

How to add UIContextMenuInteraction to button on Xamarin Forms?

我需要向 Xamarin 的按钮添加上下文菜单 iOS。 我在 Apple 开发者网站上找到了 example

所以我需要做一个非常相似的上下文菜单,但它应该锚定到按钮元素。

我创建了控件并将其命名为 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);
    }
}

此外,我为控件创建了一个简单的 iOS 渲染器 -

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

问题是我不知道应该如何构建 UIContextMenuInteraction。我们应该将 IUIContextMenuInteractionDelegate 类型的实例传递给 UIContextMenuInteraction 对象。 我找不到任何有关如何操作的示例。我所拥有的只是苹果开发者网站上的一个例子:

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])
        }
    }
}

是否有一种简单的方法可以将上下文菜单交互添加到我的本机控件?

我用下面的代码测试它工作正常,只要长按按钮就会显示菜单。

交互按钮

    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}"/>

自定义渲染器

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