Joel Fischer
Joel Fischer

Reputation: 6597

iOS 14 present UIMenu from UIView

iOS 14's UIMenu seems to be able to be presented from any UIBarButtonItem or UIButton / UIControl, but I how would I present it from a generic UIView?

Upvotes: 8

Views: 4053

Answers (3)

Alexandr Hotko
Alexandr Hotko

Reputation: 83

You can add fake transparent UIButton with UIMenu over your view.

UIView * targetView = [ [ UIView alloc ] init ]; // - your view

UIButton * fakeButton = [ [ UIButton alloc ] init ];
fakeButton.showsMenuAsPrimaryAction = YES;
UIAction * action = [ UIAction actionWithTitle:@"Test" image:nil identifier:nil handler:^(__kindof UIAction * _Nonnull action)
{
    //
} ];
fakeButton.menu = [ UIMenu menuWithChildren:[ NSArray arrayWithObject:action ] ];
[ targetView addSubview:fakeButton ];

Don't forget synchronize frame, like

fakeButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

or

fakeButton.frame = targetView.bounds;

Upvotes: 0

Plato
Plato

Reputation: 621

You cannot present a menu directly from a UIView as of now.

The best workaround is to add a UIButton as a subview, and use the UIButton to present the menu. This will work without a long press.

button.menu = UIMenu(title: "", image: nil, identifier: nil, options: [], children: menuActions)
button.showsMenuAsPrimaryAction = true
view.addSubview(button)
view.sendSubviewToBack(button)
//add necessary constraints to position the button as you please

Note: do not use "UIContextMenuInteraction" with the UIButton or it will require a long press. Thanks to @HangarRash for pointing this out.

Upvotes: 0

TonyMkenu
TonyMkenu

Reputation: 7667

Add the interaction:

let interaction = UIContextMenuInteraction(delegate: self)
menuView.addInteraction(interaction)

Add UIContextMenuInteractionDelegate to your controller:

extension YourViewController: UIContextMenuInteractionDelegate {
               
      func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
        return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { suggestedActions in
            
            // Create an action for sharing
            let share = UIAction(title: "Share", image: UIImage(systemName: "square.and.arrow.up")) { action in
                // Show system share sheet
            }
    
            // Create an action for renaming
            let rename = UIAction(title: "Rename", image: UIImage(systemName: "square.and.pencil")) { action in
                // Perform renaming
            }
    
            // Here we specify the "destructive" attribute to show that it’s destructive in nature
            let delete = UIAction(title: "Delete", image: UIImage(systemName: "trash"), attributes: .destructive) { action in
                // Perform delete
            }
    
            // Create and return a UIMenu with all of the actions as children
            return UIMenu(title: "", children: [share, rename, delete])
        }
    }
}

Now, long-press on the view and see your menu :)

More here: https://kylebashour.com/posts/context-menu-guide

Upvotes: 3

Related Questions