iosswiftuikituimenu

Change the location of an UImenu in swift


I want to add an UIMenu to my application, I was practicing with it and now have the question if is possible to set the location of the UIMenu a little higher than the button is currently displaying it:

Menu above button

as you can see in this photo the menu currently overlay the tab bar and I wanted to set it a little higher than than the tab bar. here is my code:

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

btnMenuExtras.menu = menu

Solution

  • iOS 14+

    Sinse iOS 14 UIControl has method that provides point to which attach a menu

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

    so you can override UIButton to provide desired location for a menu (calculated or hardcoded) relatively to the button itself (`cause it is in button's coordinate space) and use that button either in storyboard (as a class for control) or created programmatically (if you need to inject it somewhere):

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

    demo

    Result:

    demo1

    Demo prepared & tested with Xcode 13 / iOS 15