【问题标题】:iOS 14 Context Menu from UIView (Not from UIButton or UIBarButtonItem)来自 UIView 的 iOS 14 上下文菜单(不是来自 UIButton 或 UIBarButtonItem)
【发布时间】:2021-06-22 22:05:34
【问题描述】:

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

anyUIView.addInteraction(UIContextMenuInteraction(delegate: self))

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

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

这似乎没有模糊,但它似乎只附加到UIButtonUIBarButtonItem

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?

【问题讨论】:

    标签: ios swift contextmenu uimenuitem uiaction


    【解决方案1】:

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

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

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

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

    典型结果:

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

    当然,它仍然是一个长按手势。我怀疑对此无能为力!如果这是一个普通的 UILongPressGestureRecognizer,你可能会找到它并缩短它的 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
        }
    }
    

    还有:

    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)
    

    结果是一个简单的点击召唤菜单,看起来像这样:

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

    【讨论】:

      猜你喜欢
      • 2014-09-01
      • 1970-01-01
      • 2014-02-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多