Neste tutorial, estaremos analisando detalhadamente os recursos que o Android TextInputLayout nos proporciona. O Android TextInputLayout é um componente de design que faz parte da Material Design Support Library.
Android TextInputLayout
Android TexInputLayout estende LinearLayout. O uso principal de um TextInputLayout é atuar como um invólucro para EditText (ou seu descendente) e permitir animações de dica flutuante. Regra geral: TextInputLayout deve envolver TextInputEditText em vez do normal EditText. Motivo? TextInputEditText é uma subclasse de EditText e é projetado para ser usado como filho do TextInputLayout. Além disso, usar EditText em vez disso nos daria um aviso: EditText adicionado não é um TextInputEditText. Por favor, mude para usar essa classe
. TextInputLayout oferece muito mais do que apenas exibir rótulos de dica flutuante.
Recursos do Android TextInputLayout
Alguns dos recursos que abordaremos neste tutorial são:
- Ativar/Desativar dicas flutuantes
- Ativar/Desativar animação de dica flutuante
- Exibir mensagens de erro
- Mostrar contador de caracteres
- Alarmar o usuário quando o Limite de Caracteres Excede
- Personalizando a Aparência do Texto para dica flutuante, rótulo de erro, contador de caracteres
- Alternar Visibilidade da Senha
Vamos analisar cada um desses recursos e implementá-los em um Projeto Android Studio.
Estrutura do Projeto de Exemplo Android TextInputLayout
Este é um aplicativo de única atividade. Faremos tudo dentro do layout, atividade e arquivos
styles.xml
e colors.xml
. Primeiro, adicione a dependência para a biblioteca de suporte de design dentro do arquivo build.gradle
como mostrado abaixo.
compile 'com.android.support:design:25.3.1'
Habilitando/Desabilitando Dicas Flutuantes
As Dicas Flutuantes estão habilitadas por padrão em um TextInputLayout. Para desabilitá-las, precisamos adicionar o seguinte atributo dentro da tag: app:hintEnabled="false"
. O código xml abaixo é do layout activity_main.xml
e possui três 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>
O terceiro campo EditText tem a dica flutuante desativada. Vamos ver a saída que o código acima nos dá:
Habilitando/Desabilitando Animação da Dica Flutuante
Similar à funcionalidade anterior, a animação da dica flutuante está habilitada por padrão. Para desativá-la, precisamos adicionar o seguinte atributo dentro da tag TextInputLayout. app:hintAnimationEnabled="false"
O código XML abaixo é do layout activity_main.xml
e possui campos EditText para um dos 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>
A saída do código acima é mostrada abaixo. É digno de nota mencionar que o segundo campo EditText não anima a dica flutuante quando focado.
Estilizando o Texto da Dica TextAppearance
Para usar um textColor
personalizado e textSize
para as dicas, é usado o seguinte atributo: app:hintTextAppearance="@style/HintText"
O estilo HintText é escrito dentro do arquivo styles.xml
como mostrado abaixo
<style name="HintText" parent="TextAppearance.Design.Hint">
<item name="android:textSize">16sp</item>
<item name="android:textColor">@color/colorPrimary</item>
</style>
O código XML abaixo é do layout activity_main.xml
e possui campos EditText para cada um dos casos (com/sem 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>
A saída do código acima é mostrada abaixo.
Contador de Caracteres
O Contador de Caracteres é um recurso usado por várias aplicações. (Lembra do limite de caracteres do Twitter?). Defina app:counterEnabled
como true e app:counterMaxLength
com o número máximo de caracteres desejados no TextInputLayout. O Contador de Caracteres é exibido abaixo do EditText por padrão (canto inferior direito) e, ao escrever este tutorial, ainda não há maneira de mudar a posição. Estilizar o contador é semelhante à estilização do texto da dica. app:counterTextAppearance
é o atributo usado desta vez. Adicionamos o seguinte estilo dentro do arquivo styles.xml em nosso projeto.
<style name="CounterText" parent="TextAppearance.Design.Counter">
<item name="android:textSize">16sp</item>
<item name="android:textColor">@color/my_pink</item>
</style>
O código XML abaixo é do layout activity_main.xml
e possui campos EditText com um contador de caracteres padrão e um 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>
A saída do código acima é dada abaixo. Vamos observar de perto a saída acima.
- O primeiro campo EditText muda sua cor de texto do contador, cor do texto de dica e a cor do indicador quando o número de caracteres é excedido.
- O segundo campo EditText faz o mesmo, mas também muda a cor de texto do contador personalizado e o tamanho de texto personalizado quando o limite é excedido.
Para especificar o estilo que precisamos quando o contador de caracteres excede seu limite, precisamos usar o atributo counterFlow que veremos a seguir.
Overflow do Contador de Caracteres
Como vimos acima, quando o número de caracteres excede o limite definido, o texto do contador usa os atributos definidos em counterFlow. Se os atributos não estiverem presentes, ele permanecerá com os padrões, como vimos na saída acima. Precisamos usar o seguinte parâmetro app:counterOverflowTextAppearance. O estilo para CounterOverflow está presente dentro do 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>
Adicione o trecho de código abaixo ao layout 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 executar o aplicativo novamente.
Rótulo de Erro
Configurar app:errorEnabled
para true nos permite exibir um texto de erro sob condição abaixo do nosso campo EditText. Para estilizar o Texto de Erro, usaríamos o atributo app:errorTextAppearance
e adicionar o seguinte código dentro do nosso arquivo styles.xml
.
<style name="ErrorText" parent="TextAppearance.Design.Error">
<item name="android:textSize">16sp</item>
<item name="android:textColor">@color/my_black</item>
</style>
O código XML abaixo é do layout activity_main.xml
e possui campos EditText para um rótulo de erro padrão e um 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: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 exibir o texto de erro, teremos que chamar o método setError(String)
em uma instância de TextInputLayout em nossa classe MainActivity.java
, conforme mostrado abaixo.
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);
}
});
}
}
No código acima, adicionamos um `TextChangedListener` (que implementa `TextWatcher`) em cada instância de TextInputEditText. Exibimos o rótulo de erro quando a contagem de caracteres atual excede o limite máximo do contador. Para limpar o rótulo de erro, definimos o valor dentro de `setError()` como `null`. A saída que o código acima nos dá é: ` Nota: O indicador do campo de texto usa a mesma cor que o rótulo de erro. Ele substitui a cor definida por `counterOverflow`, portanto, tem a maior prioridade.
Alternar Visibilidade da Senha
Configurar `app:passwordToggleEnabled` como `true` permite mostrar/ocultar a senha. Para alterar a cor do ícone, use `app:passwordToggleTint`. O código XML abaixo é do layout `activity_main.xml` e possui campos EditText para um alternador de visibilidade de senha (ícone padrão e com uma tonalidade).
<?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>
A saída exibida pelo código acima é: Nota: Podemos usar nossos próprios ícones personalizados para alternar a visibilidade da senha usando
app:passwordToggleDrawable
. Isso encerra este tutorial. Cobrimos todos os principais recursos presentes no TextInputLayout. Você pode baixar o Projeto de Exemplo Android TextInputLayout pelo link abaixo. Ele inclui cada um dos trechos de código acima.
Baixar Projeto Android TextInputLayout
Referência: Documentação Oficial do Android
Source:
https://www.digitalocean.com/community/tutorials/android-textinputlayout-example