How to change text and background color UIMenu | UIAction (Swift 5)

3.2k Views Asked by At

Please tell me how to customize this menu? Perhaps another way to do it?

UIMenu

let barMenu = UIMenu(title: "", children: [
        UIAction(title: NSLocalizedString("menu_item_home", comment: "")){
                                action in
                                print("menu_item_home 1")
                            },
                            UIAction(title: NSLocalizedString("menu_item_settings", comment: "")){
                                action in
                                print("menu_item_settings 2")
                                
                                 let settingsStoryboard = UIStoryboard(name: "Settings", bundle: nil)
                                 let settingsController = settingsStoryboard.instantiateViewController(withIdentifier: "SettingsScene") as! SettingsViewController
                                 controller.navigationController?.pushViewController(settingsController, animated: true)
                                 
                            },
        
                            UIAction(title: NSLocalizedString("menu_item_contacts", comment: "")){
                                action in
                                print("menu_item_contacts 3")
                                
                                
                            },
                        
    ])
    
    let navBarMenu = UIBarButtonItem(image: UIImage(systemName: "text.justify"), menu: barMenu)
    navigationItem.rightBarButtonItem = navBarMenu

I need to add a menu to a NavigationBar and customize its appearance. Point in the right direction please

1

There are 1 best solutions below

0
On

Unfortunately UIMenu is not an UIView and there are very little options to customize it. There is no way to change the background or text color at least not in current iOS 15 and at least without doing some stupid workarounds. If you need to have a different appearance in this menu then perhaps you can create something similar with a custom popover instead of using UIMenu. That would give you much more customization options. Not exactly what you asked for but maybe it will fit your needs. Possible implementation of a similar menu based on a popover could look more or less like below:

class MenuViewController: UITableViewController, UIPopoverPresentationControllerDelegate {
    private var actions: [UIAction] = [] // or perhaps something custom

    convenience init(actions: [UIAction]) {
        self.init(style: .plain)
        self.actions = actions
        modalPresentationStyle = .popover
        preferredContentSize = CGSize(width: 240, height: 40 * actions.count)
        presentationController?.delegate = self
        popoverPresentationController?.permittedArrowDirections = .up
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "UITableViewCell")
        tableView.rowHeight = 40
        tableView.separatorInset = .zero
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return actions.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath)
        let action = actions[indexPath.row]
        cell.textLabel?.text = action.title
        cell.imageView?.image = action.image
        return cell
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // do something
    }

    func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
        return .none
    }
}

And then present it somewhere from your code like this:

    let menuVC = MenuViewController(actions: [
        // actions
    ])
    menuVC.popoverPresentationController?.sourceView = mySourceView
    menuVC.popoverPresentationController?.sourceRect = mySourceView.bounds
    present(menuVC, animated: true, completion: nil)