UILabel - UIMenuController 菜单项的长按手势

UILabel - Long press gesture for menu item of UIMenuController

我需要在整个应用程序中处理 UILable 上的长按 action/gesture,它应该显示这样的菜单,带有自定义菜单选项:

根据 Apple 界面指南,文本字段、文本视图、Web 视图和图像视图只能启用此菜单。

是否可以在 UILabel 中为整个应用程序添加此类操作,并通过添加自己的菜单选项打开自定义菜单?

这是一个 UILabel 子类,它处理长按以显示 UIMenuController。您还可以为用例的菜单控制器添加更多操作。

import UIKit

class MenuLabel: UILabel {

    override var canBecomeFirstResponder: Bool {
        return true
    }

    // MARK: - Init

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }

    private func commonInit() {
        isUserInteractionEnabled = true
        addGestureRecognizer(
            UILongPressGestureRecognizer(
                target: self,
                action: #selector(handleLongPressed(_:))
            )
        )
    }

    // MARK: - Actions

    internal func handleLongPressed(_ gesture: UILongPressGestureRecognizer) {
        guard let gestureView = gesture.view, let superView = gestureView.superview else {
            return
        }

        let menuController = UIMenuController.shared

        guard !menuController.isMenuVisible, gestureView.canBecomeFirstResponder else {
            return
        }

        gestureView.becomeFirstResponder()

        menuController.menuItems = [
            UIMenuItem(
                title: "Custom Item",
                action: #selector(handleCustomAction(_:))
            ),
            UIMenuItem(
                title: "Copy",
                action: #selector(handleCopyAction(_:))
            )
        ]

        menuController.setTargetRect(gestureView.frame, in: superView)
        menuController.setMenuVisible(true, animated: true)
    }

    internal func handleCustomAction(_ controller: UIMenuController) {
        print("Custom action!")
    }

    internal func handleCopyAction(_ controller: UIMenuController) {
        UIPasteboard.general.string = text ?? ""
    }

}

从中得出的关键要点是:

  • 确保标签覆盖 canBecomeFirstResponder
  • isUserInteractionEnabled 设为真
  • 在长按处理程序中调用 gestureView.becomeFirstResponder()

您可以将此标签添加到 Interface Builder 或在代码中创建。

希望对您有所帮助!