You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS13下自定义UIBarButtonItem展示UIMenu的两类问题求助

iOS13下自定义UIBarButtonItem展示UIMenu的问题解决

问题描述

在iOS13环境下,通过自定义UIBarButtonItem展示UIMenu(无法使用iOS14+ API),遇到两个问题:

  • 需要将菜单触发方式从长按改为点击;
  • 菜单显示时,自定义的barButtonItem会变成白色。

原始代码

class CollectionViewController: UIViewController, UIContextMenuInteractionDelegate {

private lazy var sizeMenu: UIMenu = { [unowned self] in
    return UIMenu(
        title: "Select size",
        image: nil,
        identifier: nil,
        options: [.displayInline],
        children: [
            UIAction(title: "Half", image: UIImage(systemName: "square.grid.2x2.fill"), handler: { _ in }),
            UIAction(title: "Third", image: UIImage(systemName: "square.grid.3x2.fill"), handler: { _ in }),
            UIAction(title: "Quarter", image: UIImage(systemName: "square.grid.4x3.fill"), handler: { _ in }),
        ]
    )
}()

func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
    return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { [unowned self] suggestedActions in
        return self.sizeMenu
    }
}

override func viewDidLoad() {
    super.viewDidLoad()

    let customBarButtonItem = UIButton()
    customBarButtonItem.setTitle("edit", for: .normal)
    customBarButtonItem.setTitleColor(.white, for: .normal)
    let interaction = UIContextMenuInteraction(delegate: self)
    customBarButtonItem.addInteraction(interaction)
    navigationItem.rightBarButtonItem = UIBarButtonItem(customView: customBarButtonItem)
}
}

问题示意图

  • 点击前:
    点击前
  • 点击后(菜单显示时按钮变白):
    点击后

解决方案

1. 改为点击触发菜单

UIContextMenuInteraction默认是长按触发,我们可以给自定义按钮添加点击事件,手动调用菜单展示方法:

  • 将customBarButtonItem改为类成员变量,方便后续访问;
  • 在viewDidLoad中给按钮添加点击目标;
  • 实现点击方法,通过UIContextMenuInteraction的presentMenu方法手动弹出菜单。

2. 解决按钮变白问题

系统展示上下文菜单时会自动修改视图的高亮状态,我们可以通过UIContextMenuInteractionDelegate的回调方法,在菜单即将显示时恢复按钮的标题颜色。

修改后的完整代码

class CollectionViewController: UIViewController, UIContextMenuInteractionDelegate {

private lazy var sizeMenu: UIMenu = { [unowned self] in
    return UIMenu(
        title: "Select size",
        image: nil,
        identifier: nil,
        options: [.displayInline],
        children: [
            UIAction(title: "Half", image: UIImage(systemName: "square.grid.2x2.fill"), handler: { _ in }),
            UIAction(title: "Third", image: UIImage(systemName: "square.grid.3x2.fill"), handler: { _ in }),
            UIAction(title: "Quarter", image: UIImage(systemName: "square.grid.4x3.fill"), handler: { _ in }),
        ]
    )
}()

// 将按钮改为类成员变量
private lazy var customBarButtonItem: UIButton = {
    let button = UIButton()
    button.setTitle("edit", for: .normal)
    button.setTitleColor(.white, for: .normal)
    return button
}()

func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
    return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { [unowned self] suggestedActions in
        return self.sizeMenu
    }
}

// 菜单即将显示时重置按钮颜色
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willDisplayMenu menu: UIMenu, for configuration: UIContextMenuConfiguration) {
    if let button = interaction.view as? UIButton {
        button.setTitleColor(.white, for: .normal)
    }
}

// 手动触发菜单展示
@objc private func showMenu() {
    guard let interaction = customBarButtonItem.interactions.first as? UIContextMenuInteraction else { return }
    interaction.presentMenu(at: customBarButtonItem.center, in: view, animated: true)
}

override func viewDidLoad() {
    super.viewDidLoad()

    let interaction = UIContextMenuInteraction(delegate: self)
    customBarButtonItem.addInteraction(interaction)
    // 添加点击事件
    customBarButtonItem.addTarget(self, action: #selector(showMenu), for: .touchUpInside)
    navigationItem.rightBarButtonItem = UIBarButtonItem(customView: customBarButtonItem)
}
}

内容的提问来源于stack exchange,提问作者Alisher Baigazin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 03:43:10