如何以编程方式触发 UIContextMenuInteraction 上下文菜单?

Posted

技术标签:

【中文标题】如何以编程方式触发 UIContextMenuInteraction 上下文菜单?【英文标题】:How to trigger UIContextMenuInteraction context menu programmatically? 【发布时间】:2019-09-01 09:31:34 【问题描述】:

我在 UINavigationController 内的 UIViewController 中将 UIButton 设置为 rightBarButtonItem,并将 ios13 上下文菜单关联到它。

长按按钮会按预期显示上下文菜单。

有没有办法通过点击按钮来显示上下文菜单(例如,通过为 .touchUpInside 事件添加目标)?

button/barButtonItem设置如下:

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

【问题讨论】:

@IvanCantarino 运气好吗?我知道 UIKit 管理与上下文菜单的所有交互,但是还有其他可以以编程方式触发的 UIKit 管理元素的示例。您可能可以(以编程方式)模拟长按,但我正在寻找更优雅的解决方案(即只需调用屏幕上的位置来呈现它)。 好吧,因为我一直在为 Mac Catalyst 应用程序寻找类似的东西,所以我设法将 UIMenuController 与库 PSMenuItem 一起使用,尽管模拟 UIContextMenu 会更好待定。 我来更新我的答案,提到 iOS 14 中的新增功能,发现您已经更新了您的问题:)。我只是建议将其添加为您自己问题的新答案,以及that's totally fine。 【参考方案1】:

iOS 14

iOS 14(第一个 Beta)现在支持所需的功能。使用以下代码点击 UIBarButtonItem 将立即显示菜单(同时避免调用 UIContextMenuInteraction 导致的模糊背景):

override func viewDidLoad() 
    super.viewDidLoad()
    
    let importAction = UIAction(title: "Import", image: UIImage(systemName: "folder"))  action in 
    let createAction = UIAction(title: "Create", image: UIImage(systemName: "square.and.pencil"))  action in 
    
    let menuBarButton = UIBarButtonItem(
        title: "Add",
        image: UIImage(systemName:"plus"),
        primaryAction: nil,
        menu: UIMenu(title: "", children: [importAction, createAction])
    )
    
    self.navigationItem.rightBarButtonItem = menuBarButton

该功能是通过提供primaryAction来实现的。

您可以使用 UIButton 实现相同的效果。在这种情况下,您需要设置

button.showsMenuAsPrimaryAction = true

UIButton 的完整代码如下所示:

override func viewDidLoad() 
    super.viewDidLoad()
   
    let button = UIButton(type: .system)
    button.setImage(UIImage(systemName: "plus"), for: .normal)
    button.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(button)
    
    NSLayoutConstraint.activate([
        button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
    ])
    
    let importAction = UIAction(title: "Import", image: UIImage(systemName: "folder"))  action in 
    let createAction = UIAction(title: "Create", image: UIImage(systemName: "square.and.pencil"))  action in 
    
    let items = [importAction, createAction]
    
    button.menu = UIMenu(title: "Add", children: items)
    button.showsMenuAsPrimaryAction = true


【讨论】:

嗨,有没有办法以编程方式选择按钮然后显示菜单?截至目前。我只能通过手动按下按钮来触发 UIMenu。我想在用户进入视图控制器时直接显示菜单。在此先感谢... 我尝试做同样的事情,但触发的事件根本不显示菜单。你有什么发现吗? button.showsMenuAsPrimaryAction点赞【参考方案2】:

上下文菜单是根据设计在发生适当手势(强制触摸或长按)时由系统自动显示的。不能手动显示。

来自docs:

上下文菜单交互对象在支持 3D Touch 的设备上跟踪 Force Touch 手势,在不支持 3D Touch 的设备上跟踪 长按 手势。

UIKit 管理所有与菜单相关的交互,并将所选操作(如果有)报告回您的应用。

更新

虽然仍然无法在 iOS 14 中手动显示上下文菜单,但现在可以将我们为上下文菜单创建的 UIMenu 显示为 pull-down menu。查看@Lobo's answer 了解如何在 iOS 14 上执行此操作。

【讨论】:

以上是关于如何以编程方式触发 UIContextMenuInteraction 上下文菜单?的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式触发 UIView 的点击手势识别器

以编程方式点击状态栏后如何触发“scrollsToTop”?

如何以编程方式在 ExtJS 4 中触发 keydown 事件

如何以编程方式触发 NavigationLink?

单击按钮时如何以编程方式触发刷新primeNG数据表

如何以编程方式触发 UIContextMenuInteraction 上下文菜单?