UIView 中的 iOS 14 上下文菜单(不是 UIButton 或 UIBarButtonItem)

Giz*_*odo 7 contextmenu ios uimenuitem swift uiaction

在 iOS 13/14 中,有一种简单的方法可以通过以下方式呈现上下文菜单UIContextMenuInteraction

anyUIView.addInteraction(UIContextMenuInteraction(delegate: self))
Run Code Online (Sandbox Code Playgroud)

对我来说,问题在于它模糊了整个用户界面。此外,这只能通过长按/触觉触摸来调用。

如果我不想模糊,可以使用操作菜单。如此处所示 https://developer.apple.com/documentation/uikit/menus_and_shortcuts/adopting_menus_and_uiactions_in_your_user_interface

在此输入图像描述

这似乎没有模糊地呈现,但它似乎只附加到 aUIButton或 a UIBarButtonItem

let infoButton = UIButton()
infoButton.showsMenuAsPrimaryAction = true
infoButton.menu = UIMenu(options: .displayInline, children: [])
infoButton.addAction(UIAction { [weak infoButton] (action) in
   infoButton?.menu = infoButton?.menu?.replacingChildren([new items go here...])
}, for: .menuActionTriggered)
Run Code Online (Sandbox Code Playgroud)

有没有办法将上下文菜单附加到长按时调用且不会模糊显示的 UIView 上?

mat*_*att 8

经过一些实验,我能够像这样消除变暗模糊。您将需要一个实用方法:

\n
extension UIView {\n    func subviews<T:UIView>(ofType WhatType:T.Type,\n        recursing:Bool = true) -> [T] {\n            var result = self.subviews.compactMap {$0 as? T}\n            guard recursing else { return result }\n            for sub in self.subviews {\n                result.append(contentsOf: sub.subviews(ofType:WhatType))\n            }\n            return result\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

现在我们使用上下文菜单交互委托方法来查找负责模糊的 UIVisualEffectView 并将其消除:

\n
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willDisplayMenuFor configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionAnimating?) {\n    DispatchQueue.main.async {\n        let v = self.view.window!.subviews(ofType:UIVisualEffectView.self)\n        if let v = v.first {\n            v.alpha = 0\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

典型结果:

\n

在此输入图像描述

\n

不幸的是,现在菜单后面的阴影为零,但这比大模糊要好。

\n

当然,它仍然是长按手势。我怀疑对此我们能做些什么!如果这是一个普通的 UILongPressGestureRecognizer,您可能可以找到它并缩短它的minimumPressDuration,但事实并非如此;你必须让自己遵守 UIContextMenuInteraction 的规则。

\n
\n

然而,话虽如此,如果可能的话,我可以想出一个更好的方法来做到这一点:让这个 UIView成为一个 UIControl!现在它的行为就像一个 UIControl。例如:

\n
class MyControl : UIControl {\n    override func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {\n        let config = UIContextMenuConfiguration(identifier: nil, previewProvider: nil, actionProvider: { _ in\n            let act = UIAction(title: "Red") { action in  }\n            let act2 = UIAction(title: "Green") { action in  }\n            let act3 = UIAction(title: "Blue") { action in  }\n            let men = UIMenu(children: [act, act2, act3])\n            return men\n        })\n        return config\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

和:

\n
let v = MyControl()\nv.isContextMenuInteractionEnabled = true\nv.showsMenuAsPrimaryAction = true\nv.frame = CGRect(x: 100, y: 100, width: 200, height: 100)\nv.backgroundColor = .red\nself.view.addSubview(v)\n
Run Code Online (Sandbox Code Playgroud)\n

结果是,只需轻按一下即可召唤菜单,如下所示:

\n

在此输入图像描述

\n

因此,如果你能摆脱这种方法,我认为它会好得多。

\n