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
相关产品推荐
相关产品推荐

