Actualizado: Mayo 2020
Después de haber hablado en el artículo anterior del curso de los controles de tipo botón, en esta nueva entrega nos vamos a centrar en otros tres componentes básicos imprescindibles en nuestras aplicaciones: las imágenes (ImageView
), las etiquetas (TextView
) y por último los cuadros de texto (EditText
).
Control ImageView [API]
El control ImageView
permite mostrar imágenes en la aplicación. La propiedad más interesante es android:src
, que permite indicar la imagen a mostrar. Nuevamente, lo normal será indicar como origen de la imagen el identificador de un recurso de nuestra carpeta /res/drawable, por ejemplo android:src="@drawable/unaimagen"
. Además de esta propiedad, existen algunas otras útiles en algunas ocasiones como las destinadas a establecer el tamaño máximo que puede ocupar la imagen, android:maxWidth
y android:maxHeight
, o para indicar cómo debe adaptarse la imagen al tamaño del control, android:scaleType
(CENTER, CENTER_CROP, CENTER_INSIDE, …). Además, como ya comentamos para el caso de los controles ImageButton
, al tratarse de un control de tipo imagen deberíamos establecer siempre la propiedad android:contentDescription
para ofrecer una breve descripción textual de la imagen, algo que hará nuestra aplicación mucho más accesible.
<ImageView android:id="@+id/imgLogo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:scaleType="centerInside" android:src="@drawable/logoandroid" android:contentDescription="logo de android" />
Si en vez de establecer la imagen a mostrar en el propio layout XML de la actividad quisiéramos establecerla mediante código utilizaríamos el método setImageResorce(…)
, pasándole el ID del recurso a utilizar como contenido de la imagen.
//Establecer la imagen por código imgLogo = findViewById(R.id.imgLogo) imgLogo.setImageResource(R.drawable.logoandroid)
Por cualquiera de los dos métodos, la imagen quedaría de la siguiente forma:
En cuanto a posibles eventos, al igual que comentamos para los controles de tipo botón en el apartado anterior, para los componentes ImageView
también podríamos implementar su evento onClick, de forma idéntica a la que ya vimos, aunque en estos casos suele ser menos frecuente la necesidad de capturar este evento.
Control TextView [API]
El control TextView
es otro de los clásicos en la programación de GUIs, las etiquetas de texto, y se utiliza para mostrar un determinado texto al usuario. Al igual que en el caso de los botones, el texto del control se establece mediante la propiedad android:text
. A parte de esta propiedad, la naturaleza del control hace que las más interesantes sean las que establecen el formato del texto mostrado, que al igual que en el caso de los botones son las siguientes: android:background
(color de fondo), android:textColor
(color del texto), android:textSize
(tamaño de la fuente), android:typeface
(fuente) y android:textStyle
(estilo del texto: normal, negrita, cursiva).
<TextView android:id="@+id/lblEtiqueta" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/verde" android:textColor="@color/blanco" android:textSize="20sp" android:textStyle="bold" android:text="@string/texto_ejemplo" />
Recuerda que los colores podemos definirlos en el fichero /app/res/values/colors.xml de la siguiente forma:
<resources> ... <color name="verde">#4CAF50</color> <color name="blanco">#FFFFFF</color> </resources>
Tras definirlos en el fichero colors.xml podemos hacer referencia a ellos desde nuestros layouts XML precediéndolos por el prefijo «@color/
» antes del nombre que le hayamos dado en su definición.
La etiqueta de texto tal cual se ha definido en el código anterior tendría el siguiente aspecto:
De igual forma, también podemos manipular estas propiedades desde nuestro código. Como ejemplo, en el siguiente fragmento recuperamos el texto de una etiqueta mediante su propiedad text
, actualizamos su contenido usando la misma propiedad, y por último le cambiamos su color de fondo con setBackgroundColor()
.
lblEtiqueta = findViewById(R.id.lblEtiqueta) val texto = lblEtiqueta.text.toString() lblEtiqueta.text = "$texto (modificado)" lblEtiqueta.setBackgroundColor(Color.RED)
Control EditText [API]
El control EditText
es el componente de edición de texto que proporciona la plataforma Android. Permite la introducción y edición de texto por parte del usuario, por lo que en tiempo de diseño la propiedad más interesante a establecer, además de su posición/tamaño y formato, es el texto a mostrar, atributo android:text
. Por supuesto si no queremos que el cuadro de texto aparezca inicializado con ningún texto, no es necesario incluir esta propiedad en el layout XML. Lo que sí deberemos establecer será la propiedad android:inputType
. Esta propiedad indica el tipo de contenido que se va a introducir en el cuadro de texto, como por ejemplo una dirección de correo electrónico (textEmailAddress
), un número genérico (number
), un número de teléfono (phone
), una dirección web (textUri
), o un texto genérico (text
). El valor que establezcamos para esta propiedad tendrá además efecto en el tipo de teclado que mostrará Android para editar dicho campo. Así, por ejemplo, si hemos indicado “text
” mostrará el teclado completo alfanumérico, si hemos indicado “phone
” mostrará el teclado numérico del teléfono, etc.
<EditText android:id="@+id/txtBasico" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="text" />
Al igual que ocurría con los botones, donde podíamos indicar una imagen que acompañara al texto del mismo, con los controles de texto podemos hacer lo mismo. Las propiedades drawableLeft
o drawableRight
nos permite especificar una imagen, a izquierda o derecha, que permanecerá fija en el cuadro de texto.
Otra opción adicional será indicar un texto de ayuda o descripción (hint), que aparecerá en el cuadro de texto mientras el usuario no haya escrito nada (en cuanto se escribe algo este texto desaparece). Para esto utilizaremos las propiedades android:hint
para indicar el texto y android:textColorHint
para indicar su color.
Veamos un ejemplo utilizando las propiedades anteriores:
<EditText android:id="@+id/txtBasico" android:layout_width="match_parent" android:layout_height="wrap_content" android:drawableLeft="@drawable/ic_usuario" android:hint="Nombre de Usuario" android:inputType="text" />
Y su aspecto sería el siguiente:
Para recuperar y establecer el texto desde nuestro código podemos utilizar la propiedad text
y el método setText()
respectivamente:
txtBasico = findViewById(R.id.txtBasico) val mitexto = txtBasico.text.toString() txtBasico.setText("Otro texto")
Un detalle que puede haber pasado desapercibido. ¿Os habéis fijado en que hemos tenido que hacer un toString()
sobre el resultado de la propiedad text
? La explicación para esto es que la propiedad text
no devuelve directamente una cadena de caracteres (String
) sino un objeto de tipo Editable
, que a su vez implementa la interfaz Spannable
. Y esto nos lleva a la característica más interesante del control EditText
, y es que no sólo nos permite editar texto plano sino también texto enriquecido o con formato. Veamos cómo y qué opciones tenemos disponibles, y para empezar comentemos algunas cosas sobre los objetos Spannable
.
Interfaz Spanned
Un objeto de tipo Spanned
es algo así como una cadena de caracteres (de hecho deriva de la interfaz CharSequence
) en la que podemos insertar otros objetos a modo de marcas o etiquetas (spans) asociados a rangos de caracteres. De esta interfaz deriva la interfaz Spannable
, que permite la modificación de estas marcas, y a su vez de ésta última deriva la interfaz Editable
, que permite además la modificación del texto.
Aunque en el apartado en el que nos encontramos nos interesaremos principalmente por las marcas de formato de texto, en principio podríamos insertar cualquier tipo de objeto.
Existen muchos tipos de span predefinidos en la plataforma que podemos utilizar para dar formato al texto (podéis consultarlos todos en la documentación oficial), entre ellos:
TypefaceSpan
. Modifica el tipo de fuente.StyleSpan
. Modifica el estilo del texto (negrita, cursiva, …).ForegroudColorSpan
oBackgroundSizeSpan
. Modifica el color frontal o de fondo del texto.AbsoluteSizeSpan
oRelativeSizeSpan
. Modifica el tamaño de fuente.
De esta forma, para crear un nuevo objeto Editable
e insertar una marca de formato podríamos hacer lo siguiente:
//Creamos un nuevo objeto de tipo Editable //Y marcamos cono fuente negrita la palabra "simulacro" (caracteres del 11-19) val str = Editable.Factory.getInstance().newEditable("Esto es un simulacro.") str.setSpan(StyleSpan(Typeface.BOLD), 11, 20, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
En este ejemplo estamos insertando un span de tipo StyleSpan
para marcar un fragmento de texto con estilo negrita. Para insertarlo utilizamos el método setSpan()
, que recibe como parámetro el objeto Span
a insertar, la posición inicial y final del texto a marcar, y un flag que indica la forma en la que el span se podrá extender al insertarse nuevo texto.
Texto con formato en controles TextView y EditText
Hemos visto cómo crear un objeto Editable
y añadir marcas de formato al texto que contiene, pero todo esto no tendría ningún sentido si no pudiéramos visualizarlo. Como ya podéis imaginar, los controles TextView
y EditText
nos van a permitir hacer esto. Veamos qué ocurre si asignamos a nuestro control EditText
el objeto Editable
que hemos creado antes:
txtBasico.text = str
Tras ejecutar este código, para lo que hemos insertado un botón “SetText” en la aplicación de ejemplo, veremos como efectivamente en el cuadro de texto aparece el mensaje con el formato esperado:
En la aplicación de ejemplo también he incluido un botón adicional “Negrita” que se encargará de convertir a estilo negrita un fragmento de texto previamente seleccionado en el cuadro de texto. Mi intención con esto es presentar los métodos y propiedades disponibles para determinar el comienzo y el fin de una selección en un control de este tipo. Para ello utilizaremos las propiedades selectionStart
y selectionEnd
, que nos devolverán el índice del primer y último carácter seleccionado en el texto. Sabiendo esto, ya sólo nos queda utilizar el método setSpan()
que ya conocemos para convertir la selección a negrita.
val texto = txtBasico.text; val ini = txtBasico.selectionStart; val fin = txtBasico.selectionEnd; texto.setSpan( StyleSpan(Typeface.BOLD), ini, fin, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
Bien, ya hemos visto cómo asignar texto con y sin formato a un cuadro de texto, pero ¿qué ocurre a la hora de recuperar texto con formato desde el control? Ya vimos que la propiedad text
devuelve un objeto de tipo Editable
y que sobre éste podíamos hacer un toString()
. Pero con esta solución estamos perdiendo todo el formato del texto, por lo que no podríamos por ejemplo salvarlo a una base de datos.
La solución a esto último pasa obviamente por recuperar directamente el objeto Editable
y serializarlo de algún modo, mejor aún si es en un formato estándar. Pues bien, en Android este trabajo ya nos viene hecho de fábrica a través de la clase Html
[API], que dispone de métodos para convertir cualquier objeto Spanned
en su representación HTML equivalente. Veamos cómo. Recuperemos el texto de la ventana anterior y utilicemos el método Html.toHtml(Spannable)
para convertirlo a formato HTML:
//Convertir a HTML el contenido del control val aux2 = Html.toHtml(txtBasico.text, Html.TO_HTML_PARAGRAPH_LINES_INDIVIDUAL);
Haciendo esto, obtendríamos una cadena de texto como la siguiente, que ya podríamos por ejemplo almacenar en una base de datos o publicar en cualquier web sin perder el formato de texto establecido:
<p>Esto es un <b>simulacro</b>.</p>
La operación contraria también es posible, es decir, cargar un cuadro de texto de Android (EditText
) o una etiqueta (TextView
) a partir de un fragmento de texto en formato HTML. Para ello podemos utilizar el método Html.fromHtml(String)
de la siguiente forma:
//Asigna texto con formato HTML txtBasico.setText( Html.fromHtml("<p>Esto es un <b>simulacro</b>.</p>", Html.FROM_HTML_MODE_LEGACY), BufferType.SPANNABLE);
Y con esto todo lo que debemos conocer por ahora sobre imágenes y cuadros de texto en Android.
CÓDIGO DEL ARTÍCULO: Puedes consultar y/o descargar el código completo de los ejemplos desarrollados en este artículo accediendo a la pagina del curso en GitHub.
20 comentarios
[…] Interfaz de usuario en Android: Controles básicos (II) […]
Seria posible poner varios botones y que segun que boton pulsaras, se fijaria un texto distinto en el edittext?
Un saludo
Muy buenos tutos.
Por supuesto que se puede, solo tienes que poner en el método onClick de cada uno de los botones el texto que quieres que se ponga con tu_edittext.setText(«Boton 1»);
Por ejemplo
Disculpen alguien sabe como crear una tabla en Android, si si me podrian ayudar porfa.
[…] (I) sgoliver Móviles, Programación 2010-09-07 Una vez repasados los controles básicos (I, II, III) que podemos utilizar en nuestras aplicaciones Android, vamos a dedicar los próximos […]
[…] varios de los controles indispensables en cualquier aplicación Android, como son los botones y los cuadros de texto, en este artículo vamos a ver cómo utilizar otros dos tipos de controles básicos en muchas […]
me podrias decir para que sirve BufferType.SPANNABLE?
muchas gracias
Hola, esta genial!
Yo tengo una duda que me gustaria compartir y ver si me puedes ayudar a resolver y con suerte pueda ayudar a otros también… El problema es que se como colocar él texto en por ejemplo centrado, abajo, etc..pero no lo necesito en ninguno de estos sitios ..sino en un lugar específico .. Cómo moverlo alli, son solo unos números los que tengo que mover no un texto realmente…..soy nueva en esto…
Espero que me podáis ayudar.
Gracias!
Hola Lara,
te animo a que expongas tu consulta en el foro de la web (http://www.sgoliver.net/foro) de forma que otros usuarios también puedan ayudarte. Saludos.
Felicidades por el curso, tengo una pregunta, me gustaría saber como puedo cambiar el foco entre varios editText. La idea es realizar una validación de 4 digitos a modo de pin, cuando introducimos un valor cambiar el foco a otro editText.
Un saludo y gracias
hola, en el apartado de la interfaz spanned creo que has cometido un fallo… a la palabra ForegroudColorSpan no le falta una N??? Seria asi: ForegrouNdColorSpan
Una pregunta, y si lo que quisiera es capturar el dato (numero) de un text edit a fin de realizar operaciones aritmeicas con dicho número? como puedo hacerlo?
Amigo muy bien encerio muy bien felicidaddes, grasias a gente como ustedes se es posible el progreso
Buenas, gracias por toda esta información.
tengo una duda, tengo un activity que mediante un botón lanza una segunda activity, esta muestra un mensaje dependiendo a unos criterios, pero quiero q ademas muestre una imagen…no se como…saludos
En la siguiente porción de código, ¿no sería ? int ini = texto.getSelectionStart();
Spannable texto = txtTexto.getText();
int ini = txtTexto.getSelectionStart();
int fin = txtTexto.getSelectionEnd();
Hola Sergio,
los métodos getSelectionStart() y getSelectionEnd() pertenecen a la clase EditText por lo que el código indicado en el artículo sería correcto.
Saludos.
Hola, mira lo que yo ando buscando el la forma de poner mi metodo de editar texto, no se si me entiendas, lo que busco que cuando selecciones el texto y te aparesca lo de copiar y pegar, ps yo quisiera adjuntar o poner esa opcion, la de editar.
«texto ejemplo» —-> [copiar // pegar // editar]…» » las comillas son el texto seleccionado
[…] Controles básicos (II): Texto e Imágenes [v3] [Actualizado] […]
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
return true;
case R.id.action_exit:
MainActivity.this.finish();
System.runFinalizersOnExit(true);
System.exit(0);
return true;
default:
return false;
}
}
cual es la funcion del .runFinalizersOnExit?
Felicidades, muy buenas aportaciones