Algo más de información sobre TextView

Antes de modificar una vista ya existente va a ser muy importante que estudies todos los métodos y escuchadores de eventos de que dispone. Una de las vistas más importantes es TextView dado que casi todas las vistas que incorporan un texto descienden de esta vista. Puede ser interesante que recuerdes alguna de sus propiedades más importantes.

 Vídeo[Tutorial]: Los atributos de la clase TextView.

A continuación, realizaremos un ejemplo algo más complejo que el anterior. Continuaremos modificando un EditText. No obstante esta clase es descendiente directa de EditText por lo que hereda todas sus propiedades. De hecho, todos los métodos utilizados en el ejercicio anterior y en el siguiente pertenecen a TextView; por lo tanto, podrían cambiarse estos ejercicios para que extendieran directamente de TextView

Para poder manipular un TextView resulta importante conocer la clase Layout (http://developer.android.com/reference/android/text/Layout.html). No confundir con el concepto de layout como un contenedor de vista. Por el contrario, esta clase es utilizada dividir un texto en varias líneas y mostrarlas en pantalla. Es decir, en un TextView es posible que todo el texto no quepa en una línea; la clase Layoutse encarga de dividirla en las líneas necesarias. Dispone de decenas de métodos que nos permiten averiguar donde será representada cada porción de texto o, dadas unas coordenadas de pantalla, saber a qué línea y carácter corresponde en el texto. Algunos de estos métodos son usados en el siguiente ejercicio.

Ejercicio paso a paso: Un EditText con palabras resaltadas.

 

En este ejercicio trataremos de mejorar el ejercicio anterior para que el  EditText  resalte las palabras incluidas en una lista. También conseguiremos que al pulsar sobre una palabra esta se incluya a la lista.

 

1.    Añade al principio de la clase EditText Tuneadolas siguientes dos variables:

       private Paint pincel2= new Paint();

       private Path path = new Path();

       private Vector<String> resaltar = new Vector<String>();

2.     En el constructor inicializa las varibles:

pincel2.setColor(Color.YELLOW);

       pincel2.setStyle(Style.FILL);

       resaltar.add("Android");

       resaltar.add("curso");

 

Nota:Cuando pulses «Ctrl+Shift+O» debes elegir android.graphics.Paint.Style.

3.     Añade al principio del método onDraw() el siguiente código:

finalLayout layout = getLayout();

       final String texto = getText().toString();

       for(String palabra : resaltar) {

          int pos = 0;

          do {

             pos = texto.indexOf(palabra, pos);

             if(pos != -1) {

                pos++;

                layout.getSelectionPath(pos, pos + palabra.length(), path);

                canvas.drawPath(path, pincel2);

             }

          } while (pos != -1);

       }

 

Empezamos obteniendo dos variables donde se almacena la distribución de líneas y el texto mostrado. Luego repetimos para todas las palabras a resaltar. La variable pos nos irá indicando la posición de cada una de estas palabras. El método indexOf() nos permite localizar la posición de la siguiente palabra o nos devuelve -1 si no encuentra más. El método getSelectionPath() permite obtener un área que cogería los caracteres comprendidos entre dos posiciones. Puede ser un rectángulo, aunque también podría corresponder a una figura más compleja si el texto seleccionado está en varias líneas. Terminamos rellenando con color amarillo el área que acabamos de obtener.

4.     Ejecuta la aplicación y verifica el resultado.

5.     Otro aspecto interesante a la hora de modificar una vista es capturar sus eventos para añadir nuevas funcionalidades. Para capturar las pulsaciones sobre la vista añade el siguiente método:

@Override

publicbooleanonTouchEvent(MotionEvent evento) {

   finalLayout layout = getLayout();

   finalString texto = getText().toString();

   intlinea = layout.getLineForVertical((int) evento.getY());

   intoffset = layout.getOffsetForHorizontal(linea,evento.getX())-1;

   String s = sacaPalabra(texto, offset);

   if(s.length() != 0 && resaltar.indexOf(s) == -1) {

      resaltar.add(s);

      invalidate();

      returntrue;

   } else{

      returnsuper.onTouchEvent(evento);

   }

}

Lo primero que tienes que advertir es que se trata de un manejador de eventos, no de un escuchador de eventos. Las diferencias se explican en el vídeo sobre gestión de eventos en Android que hemos recomendado con anterioridad. Las dos primeras líneas son idénticas al método anterior. A continuación, averiguamos la línea donde se ha pulsado y, luego, el índice del carácter (offset) donde se ha pulsado. Luego obtendremos la palabra a la que pertenece este offset. Si la palabra no está en la lista de resaltadas, la incluimos; con invalidate() indicamos al sistema que, cuando pueda, repinte la vista y devolvemos true para que el evento deje de ser propagado a otras vistas (por ejemplo, el LinearLayout que nos contiene).

No queremos perder la funcionalidad que incorpora un EditText con la pantalla táctil; por lo tanto, si el evento no era para nosotros hay que llamar al super para que procese la pulsación.

6.     Añade el siguiente método a la clase:

String sacaPalabra(String texto, int pos) {

   intini = pos;

   while(ini>0 && texto.charAt(ini)!=' ' && texto.charAt(ini)!='\n') {

      ini--;

   }

   intfin = pos;

   while(fin < texto.length() && texto.charAt(fin) != ' '

                                                                                && texto.charAt(fin) != '\n') {

      fin++;

   }

   returntexto.substring(ini, fin).trim();

}

7.     Ejecuta la aplicación y verifica como al pulsar sobre una palabra se añade a la lista de resaltadas.

 

Preguntas de repaso:  Modificación de las vistas.