¿Podemos habilitar el menú copiar copiar pegar para un UILabel
como lo es para un UITextField
?
Si no es así, y necesito convertir mi UILabel
a UITextField
, ¿cómo puedo habilitar el menú copiar copiar pegar y no permitir que se modifique el contenido?
UILabel
menú copiar y pegar trabajando en un UILabel
, solo tuve que devolver YES
para canBecomeFirstResponder
y luego llamar a [label becomeFirstResponder]
cuando dicha etiqueta debía aparecer en la pantalla. En cuanto a devolver YES
desde canBecomeFirstResponder
, puede crear una subclase o parche personalizado UILabel
usando una categoría:
@implementation UILabel (Clipboard) - (BOOL) canBecomeFirstResponder { return YES; } @end
La solución de categoría parece un poco hackosa, pero si sabes lo que estás haciendo, podría ser más fácil que crear subclases. También he puesto un proyecto de muestra en GitHub que muestra cómo mostrar un menú simple en un UILabel
.
El proyecto de muestra en github debido a la respuesta de @ zoul es el camino a seguir. En el momento de escribir esto, ese proyecto en realidad no pone nada en el portapapeles (cartón). aquí es cómo:
La implementación de este método de Change @ zoul para:
- (void) copy:(id)sender { UIPasteboard *pboard = [UIPasteboard generalPasteboard]; pboard.string = self.text; }
Para Swift 3 y Swift 4 tienes que implementar esta clase:
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) } }
En su guión gráfico solo subclase el UILabel
con clase CopyableLabel
He creado una subclase de UILabel de código abierto que muestra un UIMenuController con la opción “Copiar” al presionar prolongadamente:
HTCopyableLabel en GitHub
He bifurcado el proyecto de muestra de zoul y he agregado soporte para ARC (y un par de otras características) si alguien todavía está interesado:
https://github.com/zhbrass/UILabel-Clipboard
CopyLabel.h / .m debería ser lo que estás buscando
Reemplace el método textFieldShouldBeginEditing
la instancia textFieldShouldBeginEditing
y textFieldShouldBeginEditing
para que devuelva NO
para deshabilitar la edición.
Eche un vistazo al protocolo UITextFieldDelegate
para más detalles.
Swift 4 ☻ Xcode 9.2 . Al usar UIMenuController
podemos hacerlo.
UILabel
clase IBDesignable
personalizada de UILabel
que puedes asignar en el guión gráfico directamente
@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 } }
Salida:
Si tiene texto de UITextView
, debe usar UITextView
Establece el delegado:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { return false }
Y debería funcionar mágicamente 🙂
El proyecto github de @benvolioT es un muy buen ejemplo para copiar. Y para pegar, personalice canPerformAction:withSender:
Para más información, vea el ejemplo CopyPasteTile .