在UILabel上显示iPhone剪切拷贝粘贴菜单

时间:2023-01-20 17:40:35
  1. Can we enable the cut copy paste menu for a UILabel as it is for a UITextField?

    我们可以为UILabel启用剪切复制粘贴菜单,就像UITextField那样吗?

  2. If not, and I need to convert my UILabel to UITextField, how can I enable the cut copy paste menu and not allow the content to be modified?

    如果没有,并且我需要将我的UILabel转换为UITextField,如何启用剪切复制粘贴菜单而不允许修改内容?

9 个解决方案

#1


39  

I got the copy & paste menu working on a UILabel, I just had to return YES for canBecomeFirstResponder and later call [label becomeFirstResponder] when the said label was to come on screen. As for returning YES from canBecomeFirstResponder, you can create a custom subclass or patch UILabel using a category:

我得到了在UILabel上工作的copy & paste菜单,我只需返回YES作为canBecomeFirstResponder,然后调用[label becomeFirstResponder]当上述标签出现在屏幕上时。对于从canBecomeFirstResponder返回YES,您可以使用一个类别创建一个自定义子类或修补UILabel:

@implementation UILabel (Clipboard)

- (BOOL) canBecomeFirstResponder
{
    return YES;
}

@end

The category solution feels a bit hackish, but if you know what you’re doing it might be easier than subclassing. I have also put up a sample project on GitHub that shows how to display a simple pasteboard menu on an UILabel.

类别解决方案感觉有点陈腐,但如果你知道自己在做什么,它可能比子类化更容易。我还在GitHub上做了一个示例项目,演示如何在UILabel上显示一个简单的pasteboard菜单。

#2


24  

The sample project on github due to @zoul's answer is the way to go. At the time of this writing, that project does not actually put anything on the clipboard (pasteboard). here is how:

由于@zoul的答案,github上的样例项目是可行的。在撰写本文时,该项目实际上并没有将任何东西放到剪贴板(粘贴板)上。这里是:

Change @zoul's implementation of this method to:

将@zoul对该方法的实现更改为:

- (void) copy:(id)sender {
    UIPasteboard *pboard = [UIPasteboard generalPasteboard];
    pboard.string = self.text;  
}

#3


12  

For Swift 3 and Swift 4 you have to implement this class:

对于Swift 3和Swift 4,您必须执行此类:

import UIKit

class CopyableLabel: UILabel {

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.sharedInit()
    }

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

    func sharedInit() {
        self.isUserInteractionEnabled = true
        self.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(self.showMenu)))
    }

    @objc func showMenu(sender: AnyObject?) {
        self.becomeFirstResponder()

        let menu = UIMenuController.shared

        if !menu.isMenuVisible {
            menu.setTargetRect(bounds, in: self)
            menu.setMenuVisible(true, animated: true)
        }
    }

    override func copy(_ sender: Any?) {
        let board = UIPasteboard.general

        board.string = text

        let menu = UIMenuController.shared

        menu.setMenuVisible(false, animated: true)
    }

    override var canBecomeFirstResponder: Bool {
        return true
    }

    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        return action == #selector(UIResponderStandardEditActions.copy)
    }
}

In your storyboard just subclass the UILabel with CopyableLabel class

在故事板中,使用CopyableLabel类对UILabel进行子类化

#4


5  

I've made an open source UILabel subclass that shows a UIMenuController with a "Copy" option upon long press:

我已经创建了一个开源的UILabel子类,它显示了一个UIMenuController,在长时间按下时有一个“复制”选项:

HTCopyableLabel on GitHub

HTCopyableLabel GitHub上

#5


4  

I've forked zoul's sample project and added support for ARC (and a couple of other features) if anyone's still interested:

如果有人还感兴趣的话,我已经放弃了zoul的样例项目,并增加了对ARC(以及其他几个特性)的支持:

https://github.com/zhbrass/UILabel-Clipboard

https://github.com/zhbrass/UILabel-Clipboard

CopyLabel.h/.m should be what you're looking for

CopyLabel.h /。m应该是你要找的

#6


2  

Override the UITextField instance's textFieldShouldBeginEditing method, and set it to return NO in order to disable editing.

覆盖UITextField实例的textFieldShouldBeginEditing方法,并将其设置为返回NO以禁用编辑。

Take a look at the UITextFieldDelegate protocol for more details.

查看UITextFieldDelegate协议了解更多细节。

#7


1  

If you have multiline text, you should use UITextView

如果有多行文本,应该使用UITextView

Set the delegate:

设置委托:

func textView(_ textView: UITextView,
              shouldChangeTextIn range: NSRange,
              replacementText text: String) -> Bool {
    return false
}

And it should work magically :)

它应该神奇地发挥作用:

#8


0  

@benvolioT's github project is very good example for copying. And for paste, customize canPerformAction:withSender:. For more see example CopyPasteTile.

@benvolioT的github项目是一个很好的复制例子。对于粘贴,定制canPerformAction:withSender:。更多信息请参见示例CopyPasteTile。

#9


0  

Swift 4 ☻ Xcode 9.2. By using UIMenuController we can do it.

迅速4☻Xcode 9.2。通过使用UIMenuController我们可以做到。

I have created IBDesignable Custom UILabel class which you can assign on storyboard directly

我已经创建了IBDesignable自定义UILabel类,您可以在storyboard上直接分配该类

@IBDesignable
class TapAndCopyLabel: UILabel {

    override func awakeFromNib() {
        super.awakeFromNib()
        //1.Here i am Adding UILongPressGestureRecognizer by which copy popup will Appears
        let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPressGesture(_:)))
        self.addGestureRecognizer(gestureRecognizer)
        self.isUserInteractionEnabled = true
    }

    // MARK: - UIGestureRecognizer
    @objc func handleLongPressGesture(_ recognizer: UIGestureRecognizer) {
        guard recognizer.state == .recognized else { return }

        if let recognizerView = recognizer.view,
            let recognizerSuperView = recognizerView.superview, recognizerView.becomeFirstResponder()
        {
            let menuController = UIMenuController.shared
            menuController.setTargetRect(recognizerView.frame, in: recognizerSuperView)
            menuController.setMenuVisible(true, animated:true)
        }
    }
    //2.Returns a Boolean value indicating whether this object can become the first responder
    override var canBecomeFirstResponder: Bool {
        return true
    }
    //3.Here we are enabling copy action
    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        return (action == #selector(UIResponderStandardEditActions.copy(_:)))

    }
    // MARK: - UIResponderStandardEditActions
    override func copy(_ sender: Any?) {
        //4.copy current Text to the paste board
        UIPasteboard.general.string = text
    }
}

Output:

输出:

在UILabel上显示iPhone剪切拷贝粘贴菜单

#1


39  

I got the copy & paste menu working on a UILabel, I just had to return YES for canBecomeFirstResponder and later call [label becomeFirstResponder] when the said label was to come on screen. As for returning YES from canBecomeFirstResponder, you can create a custom subclass or patch UILabel using a category:

我得到了在UILabel上工作的copy & paste菜单,我只需返回YES作为canBecomeFirstResponder,然后调用[label becomeFirstResponder]当上述标签出现在屏幕上时。对于从canBecomeFirstResponder返回YES,您可以使用一个类别创建一个自定义子类或修补UILabel:

@implementation UILabel (Clipboard)

- (BOOL) canBecomeFirstResponder
{
    return YES;
}

@end

The category solution feels a bit hackish, but if you know what you’re doing it might be easier than subclassing. I have also put up a sample project on GitHub that shows how to display a simple pasteboard menu on an UILabel.

类别解决方案感觉有点陈腐,但如果你知道自己在做什么,它可能比子类化更容易。我还在GitHub上做了一个示例项目,演示如何在UILabel上显示一个简单的pasteboard菜单。

#2


24  

The sample project on github due to @zoul's answer is the way to go. At the time of this writing, that project does not actually put anything on the clipboard (pasteboard). here is how:

由于@zoul的答案,github上的样例项目是可行的。在撰写本文时,该项目实际上并没有将任何东西放到剪贴板(粘贴板)上。这里是:

Change @zoul's implementation of this method to:

将@zoul对该方法的实现更改为:

- (void) copy:(id)sender {
    UIPasteboard *pboard = [UIPasteboard generalPasteboard];
    pboard.string = self.text;  
}

#3


12  

For Swift 3 and Swift 4 you have to implement this class:

对于Swift 3和Swift 4,您必须执行此类:

import UIKit

class CopyableLabel: UILabel {

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.sharedInit()
    }

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

    func sharedInit() {
        self.isUserInteractionEnabled = true
        self.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(self.showMenu)))
    }

    @objc func showMenu(sender: AnyObject?) {
        self.becomeFirstResponder()

        let menu = UIMenuController.shared

        if !menu.isMenuVisible {
            menu.setTargetRect(bounds, in: self)
            menu.setMenuVisible(true, animated: true)
        }
    }

    override func copy(_ sender: Any?) {
        let board = UIPasteboard.general

        board.string = text

        let menu = UIMenuController.shared

        menu.setMenuVisible(false, animated: true)
    }

    override var canBecomeFirstResponder: Bool {
        return true
    }

    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        return action == #selector(UIResponderStandardEditActions.copy)
    }
}

In your storyboard just subclass the UILabel with CopyableLabel class

在故事板中,使用CopyableLabel类对UILabel进行子类化

#4


5  

I've made an open source UILabel subclass that shows a UIMenuController with a "Copy" option upon long press:

我已经创建了一个开源的UILabel子类,它显示了一个UIMenuController,在长时间按下时有一个“复制”选项:

HTCopyableLabel on GitHub

HTCopyableLabel GitHub上

#5


4  

I've forked zoul's sample project and added support for ARC (and a couple of other features) if anyone's still interested:

如果有人还感兴趣的话,我已经放弃了zoul的样例项目,并增加了对ARC(以及其他几个特性)的支持:

https://github.com/zhbrass/UILabel-Clipboard

https://github.com/zhbrass/UILabel-Clipboard

CopyLabel.h/.m should be what you're looking for

CopyLabel.h /。m应该是你要找的

#6


2  

Override the UITextField instance's textFieldShouldBeginEditing method, and set it to return NO in order to disable editing.

覆盖UITextField实例的textFieldShouldBeginEditing方法,并将其设置为返回NO以禁用编辑。

Take a look at the UITextFieldDelegate protocol for more details.

查看UITextFieldDelegate协议了解更多细节。

#7


1  

If you have multiline text, you should use UITextView

如果有多行文本,应该使用UITextView

Set the delegate:

设置委托:

func textView(_ textView: UITextView,
              shouldChangeTextIn range: NSRange,
              replacementText text: String) -> Bool {
    return false
}

And it should work magically :)

它应该神奇地发挥作用:

#8


0  

@benvolioT's github project is very good example for copying. And for paste, customize canPerformAction:withSender:. For more see example CopyPasteTile.

@benvolioT的github项目是一个很好的复制例子。对于粘贴,定制canPerformAction:withSender:。更多信息请参见示例CopyPasteTile。

#9


0  

Swift 4 ☻ Xcode 9.2. By using UIMenuController we can do it.

迅速4☻Xcode 9.2。通过使用UIMenuController我们可以做到。

I have created IBDesignable Custom UILabel class which you can assign on storyboard directly

我已经创建了IBDesignable自定义UILabel类,您可以在storyboard上直接分配该类

@IBDesignable
class TapAndCopyLabel: UILabel {

    override func awakeFromNib() {
        super.awakeFromNib()
        //1.Here i am Adding UILongPressGestureRecognizer by which copy popup will Appears
        let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPressGesture(_:)))
        self.addGestureRecognizer(gestureRecognizer)
        self.isUserInteractionEnabled = true
    }

    // MARK: - UIGestureRecognizer
    @objc func handleLongPressGesture(_ recognizer: UIGestureRecognizer) {
        guard recognizer.state == .recognized else { return }

        if let recognizerView = recognizer.view,
            let recognizerSuperView = recognizerView.superview, recognizerView.becomeFirstResponder()
        {
            let menuController = UIMenuController.shared
            menuController.setTargetRect(recognizerView.frame, in: recognizerSuperView)
            menuController.setMenuVisible(true, animated:true)
        }
    }
    //2.Returns a Boolean value indicating whether this object can become the first responder
    override var canBecomeFirstResponder: Bool {
        return true
    }
    //3.Here we are enabling copy action
    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        return (action == #selector(UIResponderStandardEditActions.copy(_:)))

    }
    // MARK: - UIResponderStandardEditActions
    override func copy(_ sender: Any?) {
        //4.copy current Text to the paste board
        UIPasteboard.general.string = text
    }
}

Output:

输出:

在UILabel上显示iPhone剪切拷贝粘贴菜单