【问题标题】:UILabel - Long press gesture for menu item of UIMenuControllerUILabel - UIMenuController 菜单项的长按手势
【发布时间】:2017-12-27 21:02:18
【问题描述】:

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

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

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

【问题讨论】:

  • 不需要自定义来实现这个
  • 不一定...我正在为您提供代码示例的答案。
  • @DonovanKing 很高兴在这里看到你的帮助

标签: ios swift uilabel uimenucontroller long-press


【解决方案1】:

这是一个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 或在代码中创建它。

希望这会有所帮助!

【讨论】:

  • 如果您有任何问题,请告诉我。
  • 为您寻求更多的帮助。如果我的标签文本是“显示标签菜单”并且我在用户点击的特定单词上设置菜单。我想在单词“显示”上显示菜单并将该单词仅复制到 UIPasteboard
  • 如果您希望用户选择一个单词,那么您应该使用不可编辑的 UITextView。功能是内置的,自己做会很费劲。
  • 我正在使用 Label 并部分成功并获取单词但点击索引和单词不匹配...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多