6

我想在我的应用程序中添加一个 UIMenu,我正在练习它,现在有一个问题,是否可以将位置设置为UIMenu比当前显示的按钮高一点:

按钮上方的菜单

正如您在这张照片中看到的那样,菜单当前覆盖了标签栏,我想将它设置为比标签栏高一点。这是我的代码:

let menu = UIMenu(title: "", children: [
  UIAction(title: NSLocalizedString("Gallery", comment: ""), image: UIImage(systemName: "folder"), handler: {
    (_) in
    self.loadPhotoGallery()
  })
])

btnMenuExtras.menu = menu
4

3 回答 3

4

iOS 14+

Sinse iOS 14UIControl具有提供附加菜单的点的方法

/// Return a point in this control's coordinate space to which to attach the given configuration's menu.
@available(iOS 14.0, *)
open func menuAttachmentPoint(for configuration: UIContextMenuConfiguration) -> CGPoint

因此您可以覆盖UIButton以提供相对于按钮本身的菜单(计算或硬编码)所需的位置(`因为它在按钮的坐标空间中)并在情节提要中使用该按钮(作为控制类)或以编程方式创建(如果您需要将其注入某处):

class MyButton: UIButton {
    var offset = CGPoint.zero
    override func menuAttachmentPoint(for configuration: UIContextMenuConfiguration) -> CGPoint {
        // hardcoded variant
//      return CGPoint(x: 0, y: -50)

        // or relative to orginal
        let original = super.menuAttachmentPoint(for: configuration)
        return CGPoint(x: original.x + offset.x, y: original.y + offset.y)
    }
}

class ViewController: UIViewController {

    @IBOutlet weak var btnMenuExtras: MyButton!   // << from storyboard

    override func viewDidLoad() {
        super.viewDidLoad()

        let menu = UIMenu(title: "", children: [
            UIAction(title: NSLocalizedString("Gallery", comment: ""), image: UIImage(systemName: "folder"), handler: {
                (_) in
//              self.loadPhotoGallery()
            })
        ])

        // offset is hardcoded for demo simplicity
        btnMenuExtras.offset = CGPoint(x: 0, y: -50)    // << here !!
        btnMenuExtras.menu = menu
    }
}

演示

结果:

演示1

使用 Xcode 13 / iOS 15 准备和测试的演示

于 2021-10-03T14:20:38.960 回答
1

我想扩展@Asperi 和@Jayesh Patel 的答案,关于我们如何将这项技术应用于UIBarButtonItem

//
// Technique provided by @Asperi
//
class MyButton: UIButton {
    var offset = CGPoint.zero
    override func menuAttachmentPoint(for configuration: UIContextMenuConfiguration) -> CGPoint {
        // hardcoded variant
//      return CGPoint(x: 0, y: -50)

        // or relative to orginal
        let original = super.menuAttachmentPoint(for: configuration)
        return CGPoint(x: original.x + offset.x, y: original.y + offset.y)
    }
}

let image = UIImage(systemName: "ellipsis.circle", withConfiguration: UIImage.SymbolConfiguration(scale: .default))
let button = MyButton()
button.setImage(image, for: .normal)

let menu = UIMenu(title: "", children: [
    UIAction(title: NSLocalizedString("Gallery", comment: ""), image: UIImage(systemName: "folder"), handler: {
        (_) in
    })
])
// offset is hardcoded for demo simplicity
button.offset = CGPoint(x: 0, y: 50)    // << here !!

//
// This is how we can make UIButton as UIBarButtonItem
//
button.menu = menu
button.showsMenuAsPrimaryAction = true

//
// Technique provided by @Jayesh Patel
//
let threeDotsBarButtonItem = UIBarButtonItem(customView: button)
var items = toolbar.items
items?.append(threeDotsBarButtonItem)
toolbar.items = items
于 2021-10-06T03:09:51.380 回答
1

您可以使用 UIControl 的 menuAttachmentPoint 方法为 UIButton 定位菜单并将该 UIButton 转换为 UIBarButtonItem 通过使用波纹管扩展

@available(iOS 14.0, *)
open func menuAttachmentPoint(for configuration: UIContextMenuConfiguration) -> CGPoint

extension UIButton {
  func toBarButtonItem() -> UIBarButtonItem? {
     return UIBarButtonItem(customView: self)
  }
}
于 2021-10-05T11:20:35.257 回答