iOS 14来自UIView的上下文菜单(不是来自UIButton或UIBarButtonim)

iOS 14来自UIView的上下文菜单(不是来自UIButton或UIBarButtonim),ios,swift,contextmenu,uimenuitem,uiaction,Ios,Swift,Contextmenu,Uimenuitem,Uiaction,通过UIContextMenuInteraction,在iOS 13/14中有一种简单的方式显示上下文菜单: anyUIView.addInteraction(UIContextMenuInteraction(delegate: self)) 我的问题是,它模糊了整个用户界面。此外,这只能通过长按/触觉触摸来调用 如果我不想要模糊,有动作菜单。如图所示 这看起来没有模糊,但它似乎只附加到UIButton或UIBarButtonItem let infoButton = UIButton()

通过
UIContextMenuInteraction
,在iOS 13/14中有一种简单的方式显示上下文菜单:

anyUIView.addInteraction(UIContextMenuInteraction(delegate: self))
我的问题是,它模糊了整个用户界面。此外,这只能通过长按/触觉触摸来调用

如果我不想要模糊,有动作菜单。如图所示

这看起来没有模糊,但它似乎只附加到
UIButton
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)

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

经过一些实验后,我能够移除变暗的模糊,如下所示。您将需要一个实用方法:

extension UIView {
    func subviews<T:UIView>(ofType WhatType:T.Type,
        recursing:Bool = true) -> [T] {
            var result = self.subviews.compactMap {$0 as? T}
            guard recursing else { return result }
            for sub in self.subviews {
                result.append(contentsOf: sub.subviews(ofType:WhatType))
            }
            return result
    }
}
典型结果:

不幸的是,现在菜单后面根本没有阴影,但它比大模糊要好

当然,这仍然是一个漫长的新闻姿态。我怀疑对此能做些什么!如果这是一个普通的UILongPressGestureRecognitor,您可能会找到它并缩短它的
minimumPressDuration
,但它不是;您必须遵守UIContextMenuInteraction道路规则


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

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

结果是一个简单的点击就会调用菜单,如下所示:


因此,如果你能摆脱这种做法,我认为它会更好。

这是一个非常有益的回答!
class MyControl : UIControl {
    override func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
        let config = UIContextMenuConfiguration(identifier: nil, previewProvider: nil, actionProvider: { _ in
            let act = UIAction(title: "Red") { action in  }
            let act2 = UIAction(title: "Green") { action in  }
            let act3 = UIAction(title: "Blue") { action in  }
            let men = UIMenu(children: [act, act2, act3])
            return men
        })
        return config
    }
}
let v = MyControl()
v.isContextMenuInteractionEnabled = true
v.showsMenuAsPrimaryAction = true
v.frame = CGRect(x: 100, y: 100, width: 200, height: 100)
v.backgroundColor = .red
self.view.addSubview(v)