¿Agregar texto de marcador de posición dentro de UITextView en Swift?

Resuelto StevenZ asked hace 54 años • 46 respuestas

¿Cómo puedo agregar un marcador de posición en un UITextView, similar al que puedes configurar UITextFielden Swift?

StevenZ avatar Jan 01 '70 08:01 StevenZ
Aceptado

Actualizado para Swift 4

UITextViewno tiene inherentemente una propiedad de marcador de posición, por lo que tendría que crear y manipular una mediante programación utilizando UITextViewDelegatemétodos. Recomiendo usar la solución n.° 1 o n.° 2 a continuación, según el comportamiento deseado.

Nota: Para cualquiera de las soluciones, agréguelo UITextViewDelegatea la clase y configúrelo textView.delegate = selfpara usar los métodos delegados de la vista de texto.


Solución #1 : si desea que el marcador de posición desaparezca tan pronto como el usuario seleccione la vista de texto:

Primero configure el UITextViewpara que contenga el texto del marcador de posición y configúrelo en un color gris claro para imitar el aspecto del UITextFieldtexto del marcador de posición. Hágalo en el viewDidLoadmomento de la creación de la vista de texto.

textView.text = "Placeholder"
textView.textColor = UIColor.lightGray

Luego, cuando el usuario comience a editar la vista de texto, si la vista de texto contiene un marcador de posición (es decir, si el color del texto es gris claro), borre el texto del marcador de posición y establezca el color del texto en negro para acomodar la entrada del usuario.

func textViewDidBeginEditing(_ textView: UITextView) {
    if textView.textColor == UIColor.lightGray {
        textView.text = nil
        textView.textColor = UIColor.black
    }
}

Luego, cuando el usuario termine de editar la vista de texto y renunció como primer respondedor, si la vista de texto está vacía, restablezca su marcador de posición volviendo a agregar el texto del marcador de posición y configurando su color en gris claro.

func textViewDidEndEditing(_ textView: UITextView) {
    if textView.text.isEmpty {
        textView.text = "Placeholder"
        textView.textColor = UIColor.lightGray
    }
}

Solución #2 : si desea que el marcador de posición se muestre siempre que la vista de texto esté vacía, incluso si la vista de texto está seleccionada:

Primero establezca el marcador de posición en viewDidLoad:

textView.text = "Placeholder"
textView.textColor = UIColor.lightGray

textView.becomeFirstResponder()

textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument)

(Nota: dado que el OP quería seleccionar la vista de texto tan pronto como se carga la vista, incorporé la selección de vista de texto en el código anterior. Si este no es el comportamiento deseado y no desea que se seleccione la vista de texto al cargar la vista, elimine las dos últimas líneas del fragmento de código anterior).

Luego utilice el shouldChangeTextInRange UITextViewDelegatemétodo, así:

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

    // Combine the textView text and the replacement text to
    // create the updated text string
    let currentText:String = textView.text
    let updatedText = (currentText as NSString).replacingCharacters(in: range, with: text)

    // If updated text view will be empty, add the placeholder
    // and set the cursor to the beginning of the text view
    if updatedText.isEmpty {

        textView.text = "Placeholder"
        textView.textColor = UIColor.lightGray

        textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument)
    }

    // Else if the text view's placeholder is showing and the
    // length of the replacement string is greater than 0, set 
    // the text color to black then set its text to the
    // replacement string
     else if textView.textColor == UIColor.lightGray && !text.isEmpty {
        textView.textColor = UIColor.black
        textView.text = text
    }

    // For every other case, the text should change with the usual
    // behavior...
    else {
        return true
    }

    // ...otherwise return false since the updates have already
    // been made
    return false
}

Y también implementar textViewDidChangeSelectionpara evitar que el usuario cambie la posición del cursor mientras el marcador de posición está visible. (Nota: textViewDidChangeSelectionse llama antes de que se cargue la vista, así que solo verifique el color de la vista de texto si la ventana está visible):

func textViewDidChangeSelection(_ textView: UITextView) {
    if self.view.window != nil {
        if textView.textColor == UIColor.lightGray {
            textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument)
        }
    }
}
Lyndsey Scott avatar Dec 26 '2014 02:12 Lyndsey Scott

Marcador de posición flotante


Es simple, seguro y confiable colocar una etiqueta de marcador de posición sobre una vista de texto, configurar su fuente, color y administrar la visibilidad del marcador de posición mediante el seguimiento de los cambios en el recuento de caracteres de la vista de texto.

Actualización: sugerencias incorporadas hechas por @RakshithaMurangaRodrigo en el comentario del 10 de febrero del 23

Rápido 5:

class NotesViewController : UIViewController {

    @IBOutlet var textView : UITextView!
    var placeholderLabel : UILabel!
        
    override func viewDidLoad() {
        super.viewDidLoad()
    
        textView.delegate = self
        placeholderLabel = UILabel()
        placeholderLabel.text = "Enter some text..."
        placeholderLabel.font = .italicSystemFont(ofSize: (textView.font?.pointSize)!)
        placeholderLabel.sizeToFit()
        textView.addSubview(placeholderLabel)
        placeholderLabel.frame.origin = CGPoint(x: 5, y: (textView.font?.pointSize)! / 2)
        placeholderLabel.textColor = .tertiaryLabel
        placeholderLabel.isHidden = !textView.text.isEmpty
    }
}

extension NotesViewController : UITextViewDelegate {
    func textViewDidChange(_ textView: UITextView) {
        placeholderLabel?.isHidden = !textView.text.isEmpty
    }
    func textViewDidEndEditing(_ textView: UITextView) {         
        placeholderLabel?.isHidden = !textView.text.isEmpty     
    }  
    func textViewDidBeginEditing(_ textView: UITextView) {         
        placeholderLabel?.isHidden = true     
    }
}

clearlight avatar Feb 02 '2015 04:02 clearlight

Rápido:

Agregue su vista de texto mediante programación o mediante Interface Builder, si es el último, cree la salida:

@IBOutlet weak var yourTextView: UITextView!

Agregue el delegado (UITextViewDelegate):

class ViewController: UIViewController, UITextViewDelegate {

En el método viewDidLoad, agregue lo siguiente:

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

    yourTextView.delegate = self
    yourTextView.text = "Placeholder text goes right here..."
    yourTextView.textColor = UIColor.lightGray

Ahora déjame presentarte la parte mágica, agrega esta función:

func textViewDidBeginEditing(_ textView: UITextView) {

    if yourTextView.textColor == UIColor.lightGray {
        yourTextView.text = ""
        yourTextView.textColor = UIColor.black
    }
}

Tenga en cuenta que esto se ejecutará cada vez que comience la edición, allí verificaremos las condiciones para indicar el estado, usando la propiedad de color. Configurar el texto en nilNo lo recomiendo. Inmediatamente después de eso, configuramos el color del texto deseado, en este caso, negro.

Ahora agregue esta función también:

func textViewDidEndEditing(_ textView: UITextView) {

    if yourTextView.text == "" {

        yourTextView.text = "Placeholder text ..."
        yourTextView.textColor = UIColor.lightGray
    }
}

Let me insist, do not compare to nil, i have already tried that and it would not work. We then set the values back to placeholder style, and set the color back to placeholder color because it is a condition to check in textViewDidBeginEditing.

Juan Boero avatar Aug 11 '2015 20:08 Juan Boero