En nuestro desarrollo interno hemos necesitado un componente de edición de texto que ajuste la línea una vez alcanzado el ancho especificado (lo que viene a ser word wrapping), pero que además evite la inserción de saltos de línea.
Si miramos en la documentación por controles básicos del SDK de Flex nos topamos con TextInput y TextArea. El primero es un control de única línea, de tal modo que por mucho alto que demos al mismo, solo escribirá en la misma única línea. El segundo es un campo de texto multilínea, tiene word wrap lo cual es lo que buscamos pero permite insertar saltos de línea al pulsar la tecla enter.
¿Qué hacer entonces? Internamente estos dos controles hacen uso de otro llamado TextField. Este es un componente de texto potente que permite hacer cualquier cosa que deseemos, con la contrapartida de necesitar escribir demasiadas líneas de código y no es lo que buscamos. Si ya existe un TextArea o TextInput, ¿por qué no reutilizarlos?. Bien, lo primero que hicimos fue buscar por ahí fuera y nos topamos con ejemplos en el archiconocido blog.flexexamples.com. Si bien es tentador copy&paste los ejemplos, particularmente no nos convencía adoptar esa solución:
Añadir un listener al evento textInput del TextArea y evitar la acción por defecto cuando el caracter introducido sea el de salto de línea
private function textArea_textInput(evt:TextEvent):void { if (evt.text == "\\n") { evt.preventDefault(); } }
Otra posible forma similar consiste en sobrescribir el método keyDownHandler() disponible en todos los UIComponents observando si la tecla pulsada ha sido la tecla enter:
override protected function keyDownHandler(event:KeyboardEvent):void { if (event.keyCode == Keyboard.ENTER) { event.preventDefault(); } else { super.keyDownHandler(event); } }
El porqué de que no nos guste esta forma, es porque se añade carga adicional al procesamiento al tener que añadir en primer lugar un listener interno y una comprobación y en el segundo caso, cuanto menos una comprobación. Todo esto por cambio de texto y tecla pulsada respectivamente.
Para evitar todo esto, se nos ocurre la siguiente solución, sobreescribir el método interno del TextArea que crea su propio TextField para que este no sea multilínea:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package { import mx.controls.TextArea; import mx.core.mx_internal; use namespace mx_internal; public class TextMultiline extends TextArea { public function TextMultiline() { super(); } // Sobrescribimos este método interno override mx_internal function createTextField(childIndex:int):void { super.createTextField(childIndex); // Una vez creado el textField con multilinea=true, // decimos que ahora es false. this.textField.multiline = false; } } } |
Esta solución implica sobreescribir un método interno ubicado en el namespace mx_internal. Si bien adoptar este tipo de soluciones puede ser peligrosa, al apoyarnos en un namespace interno susceptible de cambiar en un futuro, creemos que añade menos complejidad de procesamiento. Esta puede ser desprecible en los PCs actuales, pero aun así, habría que comprobar todo esto si la carga de TextAreas en la aplicación fuera numerosa.
Qué opináis vosotros: ¿Evitar el salto de línea añadiendo listeners, sobreescribiendo manejadores o sobreescribir la creación del textField interno?
Para otro post, cómo evitar que en un paste de texto en un TextArea se añadan saltos de línea. Que ya lo podría resolver el propio TextField …