En este tutorial, vamos a profundizar en las características que nos proporciona Android TextInputLayout. Android TextInputLayout es un componente de diseño que viene con la Biblioteca de Soporte de Material Design.
Android TextInputLayout
Android TextInputLayout extiende LinearLayout. El uso principal de un TextInputLayout es actuar como un contenedor para EditText (o sus descendientes) y habilitar animaciones de indicaciones flotantes. Regla general: TextInputLayout debería envolver a TextInputEditText en lugar del EditText normal. ¿La razón? TextInputEditText es una subclase de EditText y está diseñada para ser utilizada como hijo de TextInputLayout. Además, usar un EditText en su lugar nos mostraría una advertencia: Se ha añadido un EditText que no es un TextInputEditText. Por favor, cambie y utilice esa clase en su lugar
. TextInputLayout ofrece mucho más que simplemente mostrar etiquetas de indicación flotantes.
Características de Android TextInputLayout
Algunas de las características que cubriremos en este tutorial son:
- Habilitar/Deshabilitar indicaciones flotantes
- Habilitar/Deshabilitar animación de indicaciones flotantes
- Mostrar mensajes de error
- Mostrar contador de caracteres
- Alarmar al usuario cuando el recuento de caracteres excede su límite
- Personalización de la apariencia del texto para sugerencias flotantes, etiquetas de error, contador de caracteres
- Alternar la visibilidad de la contraseña
Examinaremos cada una de estas características e las implementaremos en un Proyecto de Android Studio.
Estructura del Proyecto de Ejemplo de Android TextInputLayout
Esta es una aplicación de actividad única. Realizaremos todo dentro del diseño, la actividad y los archivos
styles.xml
y colors.xml
. En primer lugar, agregue la dependencia para la biblioteca de soporte de diseño dentro del archivo build.gradle
como se muestra a continuación.
compile 'com.android.support:design:25.3.1'
Activar/Desactivar Sugerencias Flotantes
Las sugerencias flotantes están habilitadas de forma predeterminada en un TextInputLayout. Para desactivarlas, necesitamos agregar el siguiente atributo dentro de la etiqueta: app:hintEnabled="false"
. El código XML a continuación es del diseño activity_main.xml
y tiene tres campos EditText.
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
android:hint="TextInputEditText" />
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/activity_horizontal_margin">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Floating Hint Enabled Default" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
app:hintEnabled="false">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Floating Hint Disabled" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
</ScrollView>
El tercer campo EditText tiene la pista flotante desactivada. Veamos la salida que nos da el código anterior:
Habilitar/Deshabilitar la animación de la pista flotante
Similar a la característica anterior, la animación de la pista flotante está habilitada por defecto. Para desactivarla, necesitamos agregar el siguiente atributo dentro de la etiqueta TextInputLayout. app:hintAnimationEnabled="false"
El siguiente código XML es del diseño activity_main.xml
y tiene campos EditText para cualquiera de los casos.
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/activity_horizontal_margin">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Floating Hint Enabled Default" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
app:hintAnimationEnabled="false">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Hint Animation Disabled" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
</ScrollView>
La salida del código anterior se muestra a continuación. Cabe mencionar que el segundo campo EditText no anima la pista flotante al enfocarse.
Estilizando la apariencia del texto de la pista
Para usar un textColor
y textSize
personalizados para las sugerencias, se utiliza el siguiente atributo: app:hintTextAppearance="@style/HintText"
El estilo HintText se escribe dentro del archivo styles.xml
como se muestra a continuación
<style name="HintText" parent="TextAppearance.Design.Hint">
<item name="android:textSize">16sp</item>
<item name="android:textColor">@color/colorPrimary</item>
</style>
El siguiente código XML es del diseño activity_main.xml
y tiene campos EditText para cualquiera de los casos (con/sin hintTextAppearance).
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/activity_horizontal_margin">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Floating Hint Enabled" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/activity_horizontal_margin"
app:hintTextAppearance="@style/HintText">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Custom Hint TextAppearance" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
</ScrollView>
La salida del código anterior se muestra a continuación.
Contador de caracteres
El contador de caracteres es una característica utilizada por muchas aplicaciones (¿Recuerdas el límite de caracteres de Twitter?). Establece app:counterEnabled
en true y app:counterMaxLength
con el número máximo de caracteres que deseas en el TextInputLayout. Por defecto, el contador de caracteres se muestra debajo del EditText (en la esquina inferior derecha) y al escribir este tutorial, no hay forma de cambiar la posición todavía. Estilizar el contador es similar a estilizar el texto de sugerencia. app:counterTextAppearance
es el atributo utilizado esta vez. Hemos agregado el siguiente estilo dentro del archivo styles.xml en nuestro proyecto.
<style name="CounterText" parent="TextAppearance.Design.Counter">
<item name="android:textSize">16sp</item>
<item name="android:textColor">@color/my_pink</item>
</style>
El siguiente código XML es del diseño activity_main.xml
y tiene campos EditText con un contador de caracteres predeterminado y uno personalizado.
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
app:counterEnabled="true"
app:counterMaxLength="5"
app:hintTextAppearance="@style/HintText">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Character Counter Limit 10" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
app:counterEnabled="true"
app:counterMaxLength="5"
app:counterTextAppearance="@style/CounterText"
app:hintTextAppearance="@style/HintText">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Character Counter Custom TextAppearance" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
</ScrollView>
El resultado del código anterior se muestra a continuación. Observemos detenidamente el resultado anterior.
- El primer campo EditText cambia su color de texto textColor, el color de pista textColor y el color del indicador cuando se supera el límite de caracteres.
- El segundo campo EditText hace lo mismo, pero también cambia el color de texto personalizado custom textColor y el tamaño de texto personalizado custom textSize cuando se excede el límite.
Para especificar el estilo que necesitamos cuando el contador de caracteres supera su límite, debemos usar el atributo counterFlow, que veremos a continuación.
Desbordamiento del Contador de Caracteres
Como vimos anteriormente, cuando el recuento de caracteres supera el límite definido, el texto del contador utiliza los atributos definidos en counterFlow. Si los atributos no estuvieran presentes, se adherirá a los predeterminados, como vimos en el resultado anterior. Necesitamos usar el siguiente parámetro app:counterOverflowTextAppearance
. El estilo para CounterOverflow
está presente dentro de styles.xml:
<style name="CounterOverFlow" parent="TextAppearance.Design.Counter.Overflow">
<item name="android:textSize">16sp</item>
<item name="android:textColor">@color/my_orange</item>
</style>
Añade el siguiente fragmento de código al diseño anterior activity_main.xml
:
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
app:counterEnabled="true"
app:counterMaxLength="5"
app:counterOverflowTextAppearance="@style/CounterOverFlow"
app:counterTextAppearance="@style/CounterText"
app:hintTextAppearance="@style/HintText">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="CounterOverflow CustomTextAppearance" />
</android.support.design.widget.TextInputLayout>
Vamos a ejecutar la aplicación nuevamente.
Etiqueta de Error
Configurar app:errorEnabled
a true nos permite mostrar un texto de error en condiciones debajo de nuestro campo EditText. Para dar estilo al texto de error, usaríamos el atributo app:errorTextAppearance
y agregar el siguiente código dentro de nuestro archivo styles.xml
.
<style name="ErrorText" parent="TextAppearance.Design.Error">
<item name="android:textSize">16sp</item>
<item name="android:textColor">@color/my_black</item>
</style>
El siguiente código XML es del diseño activity_main.xml
y tiene campos EditText para una etiqueta de error predeterminada y una personalizada.
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:id="@+id/errorInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
app:counterEnabled="true"
app:counterMaxLength="5"
app:counterOverflowTextAppearance="@style/CounterOverFlow"
app:counterTextAppearance="@style/CounterText"
app:errorEnabled="true"
app:hintTextAppearance="@style/HintText">
<android.support.design.widget.TextInputEditText
android:id="@+id/errorEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Default Error Label" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/customErrorInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
app:counterEnabled="true"
app:counterMaxLength="5"
app:counterOverflowTextAppearance="@style/CounterOverFlow"
app:counterTextAppearance="@style/CounterText"
app:errorEnabled="true"
app:errorTextAppearance="@style/ErrorText"
app:hintTextAppearance="@style/HintText">
<android.support.design.widget.TextInputEditText
android:id="@+id/customErrorEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Custom Error Label" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
</ScrollView>
Para mostrar el texto de error, tendremos que llamar al método setError(String)
en una instancia de TextInputLayout en nuestra clase MainActivity.java
, como se muestra a continuación.
package com.journaldev.featuresoftextinputlayout;
import android.support.design.widget.TextInputEditText;
import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
public class MainActivity extends AppCompatActivity {
TextInputLayout errorInputLayout, customErrorInputLayout;
TextInputEditText errorEditText, customErrorEditText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
errorEditText = (TextInputEditText) findViewById(R.id.errorEditText);
errorInputLayout = (TextInputLayout) findViewById(R.id.errorInputLayout);
customErrorEditText = (TextInputEditText) findViewById(R.id.customErrorEditText);
customErrorInputLayout = (TextInputLayout) findViewById(R.id.customErrorInputLayout);
errorEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (s.length() > errorInputLayout.getCounterMaxLength())
errorInputLayout.setError("Max character length is " + errorInputLayout.getCounterMaxLength());
else
errorInputLayout.setError(null);
}
});
customErrorEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (s.length() > customErrorInputLayout.getCounterMaxLength())
customErrorInputLayout.setError("Max character length is " + customErrorInputLayout.getCounterMaxLength());
else
customErrorInputLayout.setError(null);
}
});
}
}
En el código anterior, agregamos un TextChangedListener
(que implementa TextWatcher) en cada instancia de TextInputEditText. Mostramos la etiqueta de error cuando el recuento de caracteres actual excede el límite máximo del contador. Para borrar la etiqueta de error, establecemos el valor dentro de setError()
como null. La salida que nos da el código anterior es: Nota: El indicador del campo de texto utiliza el mismo color que la etiqueta de error. Anula el color establecido por counterOverflow, por lo que tiene la mayor prioridad.
Alternar visibilidad de contraseña
Al establecer app:passwordToggleEnabled
en true, puedes mostrar/ocultar la contraseña. Para cambiar el color del ícono, utiliza app:passwordToggleTint
. El siguiente código XML es del diseño activity_main.xml
y tiene campos de EditText para alternar la visibilidad de la contraseña (con el ícono predeterminado y con un tinte).
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
app:counterEnabled="true"
app:counterMaxLength="5"
app:counterOverflowTextAppearance="@style/CounterOverFlow"
app:counterTextAppearance="@style/CounterText"
app:hintTextAppearance="@style/HintText"
app:passwordToggleEnabled="true">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Password Visibility Toggle"
android:inputType="textPassword" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
app:counterEnabled="true"
app:counterMaxLength="5"
app:counterOverflowTextAppearance="@style/CounterOverFlow"
app:counterTextAppearance="@style/CounterText"
app:hintTextAppearance="@style/HintText"
app:passwordToggleEnabled="true"
app:passwordToggleTint="@color/my_orange">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Password Visibility Toggle Tint"
android:inputType="textPassword" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
</ScrollView>
La salida mostrada por el código anterior es: Nota: Podemos usar nuestros propios iconos personalizados desde la alternancia de visibilidad de contraseña usando
app:passwordToggleDrawable
. Esto pone fin a este tutorial. Hemos cubierto todas las características principales presentes en TextInputLayout. Puedes descargar el Proyecto de Ejemplo de Android TextInputLayout desde el enlace a continuación. Incluye cada uno de los fragmentos de código mencionados anteriormente.
Descargar Proyecto de Android TextInputLayout
Referencia: Documentación Oficial de Android
Source:
https://www.digitalocean.com/community/tutorials/android-textinputlayout-example