Textinputlayout error style

Создание выпадающего меню

Создание выпадающего меню

Макет TextInputLayout сначала появился в библиотеке Android Design Support Library и добавляет немного красоты к текстовому полю. Когда пользователь начинает вводить текст в текстовом поле, то подсказка, заданная в этом компоненте, всплывает над ним в специальном TextView. Пример можно увидеть на видео.

Библиотека больше не развивается, поэтому используйте AndroidX, которую я и буду теперь использовать в описании.

Компонент можно найти на панели инструментов в разделе Text.

При добавлении компонента через визуальный редактор автоматически добавляется дочерний элемент TextInputEditText.


<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Main2Activity">

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/textInputLayout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <com.google.android.material.textfield.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="hint" />
    </com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

Так выглядел компонент в составе Support Library.

Подсказку не обязательно указывать в атрибуте android:hint у текстового поля. Можно программно присвоить через метод:


textInputLayout.setHint(getString(R.string.hint));

Стилизация

В AndroidX у компонента появились новые стили: OutlinedBox, FilledBox и другие. Можете самостоятельно попробовать пример с двумя стилями и посмотреть на отличия.


<com.google.android.material.textfield.TextInputLayout
    style="@style/Widget.MaterialComponents.TextInputEditText.OutlinedBox"
    ... />

<com.google.android.material.textfield.TextInputLayout
    style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox"
    ... />

Общая стилизация доступна следующим образом. Пропишем стили в styles.xml:


<!--Floating label text style-->  
<style name="MyHintText" parent="TextAppearance.AppCompat.Small">  
    <item name="android:textColor">@color/pink</item>
</style>

<!--Input field style-->  
<style name="MyEditText" parent="Theme.AppCompat.Light">  
    <item name="colorControlNormal">@color/indigo</item>
    <item name="colorControlActivated">@color/pink</item>
</style>  

Применим стили


<com.google.android.material.textfield.TextInputLayout  
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:hintTextAppearance="@style/MyHintText">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/Title"
        android:theme="@style/MyEditText" />

</com.google.android.material.textfield.TextInputLayout>

Обработка ошибки

Предыдущий пример показывал применение подсказки. Но также можно выводить сообщения об ошибке. Здесь потребуется написать немного кода. За вывод ошибки отвечает атрибут app:errorEnabled. Назначим текстовому полю тип клавиатуры и однострочный текст. При наборе текста после нажатия на клавишу Enter проверяем длину текста. Если текст меньше четырёх символов, то выводим сообщение об ошибке.


Добавить пространство имён к корневому элементу
xmlns:app="http://schemas.android.com/apk/res-auto"

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/textInputLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:errorEnabled="true">

    <EditText
        android:id="@+id/editTextName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:imeOptions="actionGo"
        android:inputType="text"
        android:singleLine="true"/>
</com.google.android.material.textfield.TextInputLayout>

Код


package ru.alexanderklimov.design;

import ...

public class MainActivity extends AppCompatActivity {

    private static final int MIN_TEXT_LENGTH = 4;
    private static final String EMPTY_STRING = "";

    private TextInputLayout mTextInputLayout;
    private EditText mEditText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        mTextInputLayout = findViewById(R.id.textInputLayout);
        mEditText = findViewById(R.id.editTextName);

        mTextInputLayout.setHint(getString(R.string.hint));
        mEditText.setOnEditorActionListener(ActionListener.newInstance(this));
    }

    private boolean shouldShowError() {
        int textLength = mEditText.getText().length();
        return textLength > 0 && textLength < MIN_TEXT_LENGTH;
    }

    private void showError() {
        mTextInputLayout.setError(getString(R.string.error));
    }

    private void hideError() {
        mTextInputLayout.setError(EMPTY_STRING);
    }

    private static final class ActionListener implements TextView.OnEditorActionListener {
        private final WeakReference<MainActivity> mainActivityWeakReference;

        public static ActionListener newInstance(MainActivity mainActivity) {
            WeakReference<MainActivity> mainActivityWeakReference = new WeakReference<>(mainActivity);
            return new ActionListener(mainActivityWeakReference);
        }

        private ActionListener(WeakReference<MainActivity> mainActivityWeakReference) {
            this.mainActivityWeakReference = mainActivityWeakReference;
        }

        @Override
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
            MainActivity mainActivity = mainActivityWeakReference.get();
            if (mainActivity != null) {
                if (actionId == EditorInfo.IME_ACTION_GO && mainActivity.shouldShowError()) {
                    mainActivity.showError();
                } else {
                    mainActivity.hideError();
                }
            }
            return true;
        }
    }
}

Текст ошибки выводится снизу от текстового поля.

TextInputLayout

Стиль для сообщения об ошибке можно стилизовать. Добавим новый атрибут.


app:errorEnabled="true"
app:errorTextAppearance="@style/ErrorText"

В файле стилей res/values/styles.xml добавим новый стиль:


<style name="ErrorText" parent="TextAppearance.AppCompat.Small">
    <item name="android:textStyle">bold|italic</item>
    <item name="android:textColor">@color/colorPrimary</item>
</style>

Теперь выводится другим цветом.

TextInputLayout

Расширенный вид стилей:


<!--Error label text style-->  
<style name="MyErrorText" parent="TextAppearance.AppCompat.Small">  
    <item name="android:textColor">@color/colorPrimary</item>
</style>

<!--Input field style-->  
<style name="MyEditText" parent="Theme.AppCompat.Light">  
    <item name="colorControlNormal">@color/indigo</item>
    <item name="colorControlActivated">@color/pink</item>
</style>  

Применяем через атрибуты app:errorTextAppearance и android:theme.


<com.google.android.material.textfield.TextInputLayout  
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:errorTextAppearance="@style/MyErrorText"
    app:errorEnabled="true">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/Title"
        android:theme="@style/MyEditText" />

</com.google.android.material.textfield.TextInputLayout>

Счётчик символов

С помощью атрибутов app:counterEnabled и app:counterMaxLength можно установить счётчик символов с указанием предела, который будет выводиться под текстовым полем.


<com.google.android.material.textfield.TextInputLayout
    ...
    app:counterEnabled="true"
    app:counterMaxLength="140">

    <EditText
        .../>

</com.google.android.material.textfield.TextInputLayout>

Counter TextInputLayout

Когда будет превышен лимит, то цвет счётчика изменится. Этот цвет можно стилизовать через стиль.


<style name="MyCounterText" parent="TextAppearance.AppCompat.Small">
    <item name="android:textColor">@android:color/holo_orange_dark</item>
</style>

Стиль применяется к атрибуту app:counterOverflowTextAppearance:


<com.google.android.material.textfield.TextInputLayout
    ...
    app:counterOverflowTextAppearance="@style/MyCounterText"
    app:counterEnabled="true"
    app:counterMaxLength="10">

Связка TextInputLayout и AutoCompleteTextView позволяет создать выпадающее меню взамен стандартного компонента Spinner. Для этого задействуем один стилей, в котором присутствует ExposedDropdownMenu.

TextInputLayout ExposedDropdownMenu

Разметка экрана.


<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.textfield.TextInputLayout
        style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <AutoCompleteTextView
            android:id="@+id/autoCompleteTextView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:inputType="none"
            android:text="Барсик" />
    </com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

В AutoCompleteTextView установлен тип android:inputType=»none», чтобы у пользователя не было возможности изменять текст. Ведь нам нужно меню, а не текстовое поле.

Для создания элементов меню воспользуемся массивом строк в ресурсах. Добавляем в res/values/strings.xml.


<string-array name="cats">
    <item>Барсик</item>
    <item>Мурзик</item>
    <item>Рыжик</item>
    <item>Васька</item>
</string-array>

Создадим отдельную разметку для элементов меню в файле res/layout/dropdown_item.xml.


<?xml version="1.0" encoding="utf-8"?>
<TextView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="14dp"
    android:textStyle="bold">
</TextView>

Присоединяем созданный макет к AutoCompleteTextView через адаптер.


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val autoCompleteTextView: AutoCompleteTextView = findViewById(R.id.autoCompleteTextView)

    val cats = resources.getStringArray((R.array.cats))
    val arrayAdapter = ArrayAdapter(this, R.layout.dropdown_item, cats)

    autoCompleteTextView.setAdapter(arrayAdapter)
}

Посмотрим на результат. Нажимаем на AutoCompleteTextView и получаем выпадающий список из массива строк.

TextInputLayout ExposedDropdownMenu

Мы получили рабочий прототип, но при повороте меню работать не будет. Проверьте самостоятельно. Поэтому немного поправим код.


class MainActivity : AppCompatActivity() {

    private lateinit var autoCompleteTextView: AutoCompleteTextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        autoCompleteTextView = findViewById(R.id.autoCompleteTextView)
    }

    override fun onResume() {
        super.onResume()

        val cats = resources.getStringArray((R.array.cats))
        val arrayAdapter = ArrayAdapter(this, R.layout.dropdown_item, cats)

        autoCompleteTextView.setAdapter(arrayAdapter)
    }
}

Можно добавить к элементам меню значок. Заодно добавим подсказку.


<com.google.android.material.textfield.TextInputLayout
    style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginStart="16dp"
    android:layout_marginEnd="16dp"
    android:hint="Коты"
    app:startIconDrawable="@drawable/ic_pets"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">

TextInputLayout ExposedDropdownMenu

TextInputEditText

Казалось бы простой компонент, никаких трудностей не возникает. Но не торопитесь. Стоит повернуть устройство в альбомный режим, как текстовое поле растянется на весь экран и никакой подсказки вы не увидите. Возможно, это баг, который когда-нибудь починят. Но проблему легко решить, если вместо стандартного EditText использовать специальный компонент TextInputEditText:


<com.google.android.material.textfield.TextInputLayout
    ...>

    <com.google.android.material.textfield.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Введите текст"/>

</com.google.android.material.textfield.TextInputLayout>

Дополнительное чтение

TextInputEditText

Реклама

TextInputLayout is the currently accepted, first party text input widget intended to match material design specs. However the widget itself does not lend itself to be easily styled to fit your needs, and documentation is sparse.

This tutorial comes from my own personal solution to theming and styling a TextInputLayout. It goes beyond just the regular theme colors but also ensuring all components of the layout (hint, label, input, error) have text appearances that you have control over.

Basic TextInputLayout

Your basic TextInputLayout starts out like this:

<android.support.design.widget.TextInputLayout
    android:id="@+id/text_input_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Field 1">
    
  <android.support.design.widget.TextInputEditText
      android:layout_width="match_parent"
      android:layout_height="wrap_content"/>
      
</android.support.design.widget.TextInputLayout>

And basic theme colors are set like this:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  <!-- Customize your theme here. -->
  <item name="colorPrimary">#3F51B5</item> // (Indigo 500)
  <item name="colorPrimaryDark">#303F9F</item> // (Indigo 700)
  <item name="colorAccent">#00897B</item> // (Teal 600)
</style>

And we get this result:

basic TextInputLayout style

Noteworthy observations:

  • Only colorAccent is used from the basic app theme colors.
  • We’ve applied a custom font via Calligraphy (Fira Sans) for effect. We see here that the hint, label, and input text are properly formatted, but error text is Roboto.

Even more annoying is when an error layout is selected, the label highlight still uses colorAccent which results in this awkward looking UI — a mix of colorAccent and red error, which may or may not clash:

what is this

Colors

Start with defining colors you want to apply:

<color name="error_color">#C62828</color> // Error color (Red 800)
<color name="hint_color_active">#00897B</color> // Active label color (Teal 600)
<color name="hint_color_inactive">#9E9E9E</color> // Inactive label / Hint (Grey 500)

And set up styles and themes like so:

<style name="MyStyle.InputLayout" parent="Widget.Design.TextInputLayout">
  <item name="fontPath">@string/app_font</item>
  <item name="errorTextAppearance">@style/ErrorTextAppearance</item>
  <item name="hintTextAppearance">@style/HintTextAppearance</item>
</style>

<style name="MyTheme.EditText" parent="Theme.AppCompat.Light">
  <!-- Inactive underline color-->
  <item name="colorControlNormal">@color/hint_color_inactive</item>
  
  <!-- Cursor and Active underline color, uses colorAccent by default if not defined-->
  <item name="colorControlActivated">@color/hint_color_active</item>
</style>

<style name="HintTextAppearance" parent="TextAppearance.Design.Hint">
  <!-- Inactive and Active label color, pointing to a selector-->
  <item name="android:textColor">@color/hint_color</item>
</style>

<style name="ErrorTextAppearance" parent="TextAppearance.Design.Error">
  <!-- Error text color-->
  <item name="android:textColor">@color/error_color</item>
</style>

// res/color/hint_color.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_focused="true" android:color="@color/hint_color_active"/>
  <item android:color="@color/hint_color_inactive"/>
</selector>

And applying them to your views:

<android.support.design.widget.TextInputLayout
    android:id="@+id/text_input_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Field 1"
    style="@style/MyStyle.InputLayout">
    
  <android.support.design.widget.TextInputEditText
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:theme="@style/MyTheme.EditText"/>
      
</android.support.design.widget.TextInputLayout>

What we can’t accomplish with pure styling alone is:

  • Error label color
  • Error view typeface
  • Error cursor color

new-style-error-select

The Error View

The way TextInputLayout manages its error view thwarts how Calligraphy works. Essentially, Calligraphy only works when inflating views that have a fontPath attribute applied — it can’t apply a font path to a programmatically created view, even if the style with a fontPath is applied programmatically. Because the error view is created programmatically (and not inflated), any fontPath provided in errorTextAppearance is simply ignored.

Another annoying caveat is the exposed setTypeface method, which is intended to allow specifying the error and hint typefaces:

// TextInputLayout
/**
 * Set the typeface to use for the hint and any label views (such as counter and error views).
 *
 * @param typeface typeface to use, or {@code null} to use the default.
 */
public void setTypeface(@Nullable Typeface typeface);

but will fail to apply the typeface to the error view if it’s invoked before setErrorEnabled(true):

public void setTypeface(@Nullable Typeface typeface) {
  ...
  
  // this is null by default until the first time setErrorEnabled(true) is invoked
  if (mErrorView != null) { 
    mErrorView.setTypeface(typeface);
  }
}

So my recommendation is to enable setErrorEnabled in TextInputLayout styles by default:

<style name="MyStyle.InputLayout" parent="Widget.Design.TextInputLayout">
  <item name="errorEnabled">true</item>
</style>

Error View: Typeface

Android 8.0 (API 26) introduced Fonts in XML and you’re encouraged to explore that solution to see if that works for you. I’ll walk through the more lengthy, Calligraphy based solution below.

Create a custom TextInputLayout, and load and apply setTypeface in the constructor using whatever fontPath is applied to the entire layout:

private static final int[] FONT_PATH = new int[] { R.attr.fontPath };

public MyTextInputLayout(...) {
    ...
    Typeface typeface = TypefaceUtils.load(context.getAssets(),
        loadFontPathFromStyle(context, attrs, FONT_PATH));

    // Only works if errorEnabled == true. Either call it here or set it in your style.
    setTypeface(typeface);
  }

  // Implementation from CalligraphyUtils#pullFontPathFromStyle
  private String loadFontPathFromStyle(Context context, AttributeSet attrs, int[] attributeId) {
    if (attributeId == null || attrs == null) return null;
    final TypedArray typedArray = context.obtainStyledAttributes(attrs, attributeId);
    if (typedArray != null) {
      try {
        // First defined attribute
        String fontFromAttribute = typedArray.getString(0);
        if (!TextUtils.isEmpty(fontFromAttribute)) {
          return fontFromAttribute;
        }
      } catch (Exception ignore) {
        // Failed for some reason.
      } finally {
        typedArray.recycle();
      }
    }
    return null;
  }

Remember this only works if errorEnabled is set to true in the style; otherwise you need override setErrorEnabled and call setTypeface yourself.

Label View: Error Active Color

We will create a custom attribute to represent the error state for our TextInputLayout implementation:

// attrs.xml
<resources>
  <declare-styleable name="ErrorState">
    <attr format="boolean" name="state_error"/>
  </declare-styleable>
</resources>
public class MyTextInputLayout extends TextInputLayout {

  private static final int[] ERROR_STATE = new int[] { R.attr.state_error };

  private boolean errorState = false;

  ...
  
  @Override
  public void setError(@Nullable CharSequence error) {
    // We'll manage the view's error state by calls to this method, which correctly reflects when the TextInputLayout hides/shows the error text
    errorState = !TextUtils.isEmpty(error);
    refreshDrawableState();
    super.setError(error);
  }
  
  @Override
  protected int[] onCreateDrawableState(int extraSpace) {
    // add a new drawable state we are defining as error state
    int[] state = super.onCreateDrawableState(extraSpace + 1);
    if (errorState) {
      View.mergeDrawableStates(state, ERROR_STATE);
    }
    return state;
  }  
}

We update the hint text color referenced in the style for hintTextAppearance to take advantage of this new state:

// res/color/hint_color.xml
<selector xmlns:app="http://schemas.android.com/apk/res-auto">
  <item app:state_error="true" android:color="@color/error_color"/>
  ...
</selector>

Add everything up and we should be able to reproduce this result, which has the correct error text view font applied, custom error label text color, custom hint and underline colors:

new-style

And selected error view behavior:

new-style-error-select

Error Cursor Color?

Have colorControlActivated also point to a selector that takes advantage of the new error state we’ve created, similar to hint_color.

Summary

Style/theme attributes can get you most places when styling the TextInputLayout, but fixing the error text typeface and tweaking the error label color takes more effort to deliver a look and feel that you want for your app outside of stock behavior.

Text fields

Text fields let users enter and
edit text.

"Text fields on a screen"

Contents

  • Using text fields
  • Filled text field
  • Outlined text field
  • Theming

Using text fields

Before you can use Material text fields, you need to add a dependency to the
Material Components for Android library. For more information, go to the
Getting started
page.

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/textField"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="@string/label">

    <com.google.android.material.textfield.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
    />

</com.google.android.material.textfield.TextInputLayout>

Note: A text field is composed of a TextInputLayout and a
TextInputEditText as a direct child. Using an EditText as the child might
work, but TextInputEditText provides accessibility support for the text field
and allows TextInputLayout greater control over the visual aspects of the
input text. If an EditText is being used, make sure to set its
android:background to @null so that TextInputLayout can set the proper
background on it.

Making text fields accessible

Android’s text field component APIs support both label text and helper text,
which explain what is requested for a text field. While optional, their use is
strongly encouraged.

Content description

When using custom icons, you should set a content description on them so
that screen readers, like TalkBack, are able to announce their purpose or
action.

For the leading icon, that can be achieved via the
app:startIconContentDescription attribute or setStartIconContentDescription
method. For the trailing icon, that can be achieved via the
app:endIconContentDescription attribute or setEndIconContentDescription
method.

When setting an error message that contains special characters that screen
readers or other accessibility systems are not able to read, you should set a
content description via the app:errorContentDescription attribute or
setErrorContentDescription method. That way the error will announce the
content description instead of the error message.

Note: Icons that don’t have click listeners set on them work as decorative
elements, and are therefore skipped by screen readers.

Custom EditText

If you are using a custom EditText as TextInputLayout‘s child and your text
field requires different accessibility support than the one offered by
TextInputLayout, you can set a TextInputLayout.AccessibilityDelegate via the
setTextInputAccessibilityDelegate method. This method should be used in place
of providing an AccessibilityDelegate directly on the EditText.

Adding a leading icon to a text field

"Text field with a leading icon."

<com.google.android.material.textfield.TextInputLayout
    ...
    app:startIconDrawable="@drawable/ic_search_24dp"
    app:startIconContentDescription="@string/content_description_start_icon">

    ...

</com.google.android.material.textfield.TextInputLayout>

Adding a trailing icon to a text field

Password toggle:

"Text field with a password toggle trailing icon."

When the TextInputEditText is set to display a password, an icon can be added
to toggle between masking the password or displaying the password as plain-text.

<com.google.android.material.textfield.TextInputLayout
    ...
    app:endIconMode="password_toggle">

    <com.google.android.material.textfield.TextInputEditText
        ...
        android:inputType="textPassword"
    />

</com.google.android.material.textfield.TextInputLayout>

Clear text:

"Text field with a clear text trailing icon."

An icon can be set to display when text is present. The icon can be pressed to
clear the input text.

<com.google.android.material.textfield.TextInputLayout
    ...
    app:endIconMode="clear_text">

    ...

</com.google.android.material.textfield.TextInputLayout>

Custom icon:

"Text field with a custom trailing icon."

It is possible to set a custom Drawable as the text field’s trailing icon via
app:endIconMode="custom". You should specify a drawable and content
description for the icon, and you have the option to specify custom behaviors.

In the layout:

<com.google.android.material.textfield.TextInputLayout
    ...
    app:endIconMode="custom"
    app:endIconDrawable="@drawable/ic_accelerator_24dp"
    app:endIconContentDescription="@string/content_description_end_icon">

    ...

</com.google.android.material.textfield.TextInputLayout>

Optionally, in code:

textField.setEndIconOnClickListener {
  // Respond to end icon presses
}

textField.addOnEditTextAttachedListener {
  // If any specific changes should be done when the edit text is attached (and
  // thus when the trailing icon is added to it), set an
  // OnEditTextAttachedListener.

  // Example: The clear text icon's visibility behavior depends on whether the
  // EditText has input present. Therefore, an OnEditTextAttachedListener is set
  // so things like editText.getText() can be called.
}

textField.addOnEndIconChangedListener {
  // If any specific changes should be done if/when the endIconMode gets
  // changed, set an OnEndIconChangedListener.

  // Example: If the password toggle icon is set and a different EndIconMode
  // gets set, the TextInputLayout has to make sure that the edit text's
  // TransformationMethod is still PasswordTransformationMethod. Because of
  // that, an OnEndIconChangedListener is used.
}

Note: You should opt to use the EndIconMode API instead of setting an
end/right compound Drawable on the TextInputEditText. The same applies to
the now-deprecated passwordToggle* attributes.

Important: Calling setEndIconMode will initialize the icon with its
default features, such as default drawables, and in the case of the custom mode,
an empty drawable. You can add customizations after calling setEndIconMode.
The exception for this is if a drawable was specified in XML via the
app:endIconDrawable attribute. An end icon drawable set in XML will take
precedence and override an existing default icon.

See the full list of
end icon modes.

Implementing an exposed dropdown menu

"Text field with an exposed dropdown menu."

In the layout:

<com.google.android.material.textfield.TextInputLayout
    ...
    style="@style/Widget.Material3.TextInputLayout.*.ExposedDropdownMenu">

    <AutoCompleteTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="none"
        app:simpleItems="@array/simple_items"
    />

</com.google.android.material.textfield.TextInputLayout>

The string array specified by app:simpleItems will be used as the default
item strings for auto-completion. Or you can also set it programmatically:

val items = arrayOf("Item 1", "Item 2", "Item 3", "Item 4")
(textField.editText as? MaterialAutoCompleteTextView)?.setSimpleItems(items)

Alternatively, to have more control over the auto-completion items rendering,
you can also provide a custom item adapter by:

val items = listOf("Item 1", "Item 2", "Item 3", "Item 4")
val adapter = ArrayAdapter(requireContext(), R.layout.list_item, items)
(textField.editText as? AutoCompleteTextView)?.setAdapter(adapter)

And a custom item layout (list_item.xml):

<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="16dp"
    android:ellipsize="end"
    android:maxLines="1"
    android:textAppearance="?attr/textAppearanceTitleMedium"
/>

Adding helper text to a text field

"Text field with helper text."

<com.google.android.material.textfield.TextInputLayout
    ...
    app:helperTextEnabled="true"
    app:helperText="@string/helper_text">

    ...

</com.google.android.material.textfield.TextInputLayout>

Adding a counter to a text field

"Text field with a counter."

<com.google.android.material.textfield.TextInputLayout
    ...
    app:counterEnabled="true"
    app:counterMaxLength="20">

    ...

</com.google.android.material.textfield.TextInputLayout>

Adding errors to a text field

"Text field with an error."

In the layout:

<com.google.android.material.textfield.TextInputLayout
    ...
    app:errorEnabled="true">

    ...

</com.google.android.material.textfield.TextInputLayout>

In code:

// Set error text
passwordLayout.error = getString(R.string.error)

// Clear error text
passwordLayout.error = null

Note: Non-null error text will replace any existing helper text, and
non-null helper text will replace any existing error text.

Adding a prefix/suffix to a text field

"Text field with a prefix/suffix."

<com.google.android.material.textfield.TextInputLayout
    ...
    app:prefixText="@string/prefix"
    app:suffixText="@string/suffix">

    ...

</com.google.android.material.textfield.TextInputLayout>

Text field dimensions

The recommended default android:layout_width is 245dp.

By default, text fields have a maximum width of 488dp, and a minimum width of
56dp for layouts without a label. If a label is present, the minimum width
recommended is 88dp. android:minWidth and android:maxWidth (as well as
android:minEms and android:maxEms) should be set on the TextInputLayout
instead of on the TextInputEditText to avoid unintended behaviors.

You can override those values in a custom style that inherits from a
TextInputLayout style or by making changes directly on the layout:

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/textField"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:minWidth="@dimen/custom_min_width"
    android:maxWidth="@dimen/custom_max_width"
    android:hint="@string/label">

    <com.google.android.material.textfield.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
    />

</com.google.android.material.textfield.TextInputLayout>

Note: The android:layout_width of the TextInputLayout should be
wrap_content in order for those minimum and maximum dimensions to be used.

Using text fields programmatically

If you construct the TextInputEditText child of a TextInputLayout
programmatically, you should use TextInputLayout‘s context to create the view.
This will allow TextInputLayout to pass along the appropriate styling to the
edit text.

val textInputLayout = TextInputLayout(context)
val editText = TextInputEditText(textInputLayout.context)

Types

There are two types of text fields: 1. Filled text field,
2. Outlined text field

"Text field types. Fixed: grey back, dark gray indicator turns purple. Outlined: clear back, gray outline turns purple"

Filled text field

Filled text fields
have more visual emphasis than outlined text fields, making them stand out when
surrounded by other content and components.

Filled text field examples

API and source code:

  • TextInputLayout
    • Class definition
    • Class source
  • TextInputEditText
    • Class definition
    • Class source

The following example shows a filled text field with a label.

Filled text field

In the layout:

<com.google.android.material.textfield.TextInputLayout
    style="?attr/textInputFilledStyle"
    android:id="@+id/filledTextField"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="@string/label">

    <com.google.android.material.textfield.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
    />

</com.google.android.material.textfield.TextInputLayout>

In code:

// Get input text
val inputText = filledTextField.editText?.text.toString()

filledTextField.editText?.doOnTextChanged { inputText, _, _, _ ->
    // Respond to input text change
}

See the using text fields section above for more examples.

Anatomy and key properties

A filled text field has a filled container, input text, a label, an activation
indicator, optional helper/error text and optional leading/trailing icons.

Filled text field anatomy

  1. Container
  2. Leading icon
  3. Label
  4. Input text
  5. Trailing icon
  6. Activation indicator
  7. Helper/error/counter text
  8. Prefix/suffix/placeholder (not shown)

Note: All the attributes in the tables below should be set on the
TextInputLayout, with the exception of the input text attributes, which should
be set on the TextInputEditText.

Container attributes

Element Attribute Related method(s) Default value
Color app:boxBackgroundColor setBoxBackgroundColor
setBoxBackgroundColorResource
getBoxBackgroundColor
?attr/colorSurfaceVariant (see all states)
Shape app:shapeAppearance N/A ?attr/shapeAppearanceSmallComponent
Text field enabled android:enabled setEnabled true

Leading icon attributes

Element Attribute Related method(s) Default value
Icon app:startIconDrawable setStartIconDrawable
getStartIconDrawable
null
Content description app:startIconContentDescription setStartIconContentDescription
getStartIconContentDescription
null
Color app:startIconTint setStartIconTintList ?attr/colorOnSurfaceVariant (see all states)
Checkable app:startIconCheckable setStartIconCheckable
isStartIconCheckable
false
Size app:startIconMinSize setStartIconMinSize
getStartIconMinSize
48dp
Scale type app:startIconScaleType setStartIconScaleType
getStartIconScaleType
ScaleType.CENTER

Label attributes

Element Attribute Related method(s) Default value
Text android:hint setHint
getHint
null
Color android:textColorHint setDefaultHintTextColor
getDefaultHintTextColor
?attr/colorOnSurfaceVariant (see all states)
Collapsed (floating) color app:hintTextColor setHintTextColor
getHintTextColor
?attr/colorPrimary (see all states)
Typography app:hintTextAppearance setHintTextAppearance ?attr/textAppearanceBodySmall
Animation app:hintAnimationEnabled setHintAnimationEnabled
isHintAnimationEnabled
true
Expanded enabled app:expandedHintEnabled setExpandedHintEnabled
isExpandedHintEnabled
true

Note: The android:hint should always be set on the TextInputLayout
instead of on the EditText in order to avoid unintended behaviors.

Input text attributes

Element Attribute Related method(s) Default value
Input text android:text setText
getText
@null
Typography android:textAppearance setTextAppearance ?attr/textAppearanceBodyLarge
Input text color android:textColor setTextColor
getTextColors
getCurrentTextColor
?attr/colorOnSurface
Cursor color N/A (color comes from the theme attr ?attr/colorControlActivated) N/A ?attr/colorPrimary
Text highlight color N/A (color comes from the theme attr ?android:attr/textColorHighlight) N/A @color/m3_highlighted_text

Note: The input text attributes should be set on the TextInputEditText.

Trailing icon attributes

Element Attribute Related method(s) Default value
Mode app:endIconMode setEndIconMode
getEndIconMode
END_ICON_NONE
Color app:endIconTint setEndIconTintList colorOnSurfaceVariant (see all states)
Custom icon app:endIconDrawable setEndIconDrawable
getEndIconDrawable
null
Custom icon content description app:endIconContentDescription setEndIconContentDescription
getEndIconContentDescription
null
Custom icon checkable app:endIconCheckable setEndIconCheckable
isEndIconCheckable
true
Error icon app:errorIconDrawable setErrorIconDrawable
getErrorIconDrawable
@drawable/mtrl_ic_error
Error icon color app:errorIconTint setErrorIconTintList ?attr/colorError
Size app:endIconMinSize setEndIconMinSize
getEndIconMinSize
48dp
Scale type app:endIconScaleType setEndIconScaleType
getEndIconScaleType
ScaleType.CENTER

Activation indicator attributes

Element Attribute Related method(s) Default value
Color app:boxStrokeColor setBoxStrokeColor
setBoxStrokeColorStateList
getBoxStrokeColor
?attr/colorOutline and ?attr/colorPrimary (focused) (see all states)
Error color app:boxStrokeErrorColor setBoxStrokeErrorColor
getBoxStrokeErrorColor
?attr/colorError
Width app:boxStrokeWidth N/A 1dp
Focused width app:boxStrokeWidthFocused N/A 2dp

Helper/error/counter text attributes

Element Attribute Related method(s) Default value
Helper text enabled app:helperTextEnabled setHelperTextEnabled
isHelperTextEnabled
false
Helper text app:helperText setHelperText
getHelperText
null
Helper text color app:helperTextColor setHelperTextColor
getHelperTextColor
?attr/colorOnSurfaceVariant (see all states)
Helper text typography app:helperTextAppearance setHelperTextAppearance ?attr/textAppearanceBodySmall
Error text enabled app:errorEnabled setErrorEnabled
isErrorEnabled
false
Error text N/A setError
getError
null
Error text accessibility live region app:errorAccessibilityLiveRegion setErrorAccessibilityLiveRegion
getErrorAccessibilityLiveRegion
ViewCompat.ACCESSIBILITY_LIVE_REGION_POLITE
Error text color app:errorTextColor setErrorTextColor
getErrorCurrentTextColors
?attr/colorError
Error text typography app:errorTextAppearance setErrorTextAppearance ?attr/textAppearanceBodySmall
Counter text enabled app:counterEnabled setCounterEnabled
isCounterEnabled
false
Counter text length app:counterMaxLength setCounterMaxLength
getCounterMaxLength
-1
Counter text typography app:counterTextAppearance
app:counterOverflowTextAppearance
setCounterTextAppearance
setCounterOverflowTextAppearance
?attr/textAppearanceBodySmall
Counter text color app:counterTextColor
app:counterOverflowTextColor
setCounterTextColor
setCounterOverflowTextColor
getCounterTextColor
getCounterOverflowTextColor
?attr/colorOnSurfaceVariant (app:counterTextColor) (see all states)
?attr/colorError (app:counterOverflowTextColor)

Prefix/suffix attributes

Element Attribute Related method(s) Default value
Prefix app:prefixText setPrefixText
getPrefixText
null
Prefix color app:prefixTextColor setPrefixTextColor
getPrefixTextColor
?attr/colorOnSurfaceVariant (see all states)
Prefix typography app:prefixTextAppearance setPrefixTextAppearance ?attr/textAppearanceTitleMedium
Suffix app:suffixText setSuffixText
getSuffixText
null
Suffix color app:suffixTextColor setSuffixTextColor
getSuffixTextColor
?attr/colorOnSurfaceVariant (see all states)
Suffix typography app:suffixTextAppearance setSuffixTextAppearance ?attr/textAppearanceTitleMedium

Styles

Element Style Default style theme attribute
Default style Widget.Material3.TextInputLayout.FilledBox ?attr/textInputFilledStyle
Dense style Widget.Material3.TextInputLayout.FilledBox.Dense ?attr/textInputFilledDenseStyle
Exposed dropdown menu style Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu ?attr/textInputFilledExposedDropdownMenuStyle
Dense exposed dropdown menu style Widget.Material3.TextInputLayout.FilledBox.Dense.ExposedDropdownMenu N/A

See the full list of
styles
and
attrs.

Outlined text field

Outlined text fields
have less visual emphasis than filled text fields. When they appear in forms,
for example, where many text fields are placed together, their reduced emphasis
helps simplify the layout.

Note: The outlined text field is the default style.

Outlined text field examples

API and source code:

  • TextInputLayout
    • Class definition
    • Class source
  • TextInputEditText
    • Class definition
    • Class source

The following example shows an outlined text field.

Outlined text field

In the layout:

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/outlinedTextField"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="@string/label">

    <com.google.android.material.textfield.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
    />

</com.google.android.material.textfield.TextInputLayout>

In code:

// Get input text
val inputText = outlinedTextField.editText?.text.toString()

outlinedTextField.editText?.doOnTextChanged { inputText, _, _, _ ->
    // Respond to input text change
}

See the using text fields section above for more examples.

Anatomy and key properties

An outlined text field has a stroked container, input text, a label, optional
helper/error text and optional leading/trailing icons.

Outlined text field anatomy

  1. Container
  2. Leading icon
  3. Label
  4. Input text
  5. Trailing icon
  6. Helper/error/counter text
  7. Prefix/suffix/placeholder (not shown)

Note: All the attributes in the tables below should be set on the
TextInputLayout, with the exception of the input text attributes, which should
be set on the TextInputEditText.

Container attributes

Element Attribute Related method(s) Default value
Stroke color app:boxStrokeColor setBoxStrokeColor
setBoxStrokeColorStateList
getBoxStrokeColor
?attr/colorOutline and ?attr/colorPrimary (focused) (see all states)
Stroke error color app:boxStrokeErrorColor setBoxStrokeErrorColor
getBoxStrokeErrorColor
?attr/colorError
Stroke width app:boxStrokeWidth N/A 1dp
Stroke focused width app:boxStrokeWidthFocused N/A 2dp
Shape app:shapeAppearance N/A ?attr/shapeAppearanceSmallComponent
Text field enabled android:enabled setEnabled true

Leading icon attributes

Element Attribute Related method(s) Default value
Icon app:startIconDrawable setStartIconDrawable
getStartIconDrawable
null
Content description app:startIconContentDescription setStartIconContentDescription
getStartIconContentDescription
null
Color app:startIconTint setStartIconTintList ?attr/colorOnSurfaceVariant (see all states)
Checkable app:startIconCheckable setStartIconCheckable
isStartIconCheckable
false

Label attributes

Element Attribute Related method(s) Default value
Text android:hint setHint
getHint
null
Color android:textColorHint setDefaultHintTextColor
getDefaultHintTextColor
?attr/colorOnSurfaceVariant (see all states)
Collapsed (floating) color app:hintTextColor setHintTextColor
getHintTextColor
?attr/colorPrimary
Typography app:hintTextAppearance setHintTextAppearance ?attr/textAppearanceBodySmall

Note: The android:hint should always be set on the TextInputLayout
instead of on the EditText in order to avoid unintended behaviors.

Input text attributes

Element Attribute Related method(s) Default value
Input text android:text setText
getText
@null
Typography android:textAppearance setTextAppearance ?attr/textAppearanceBodyLarge
Input text color android:textColor setTextColor
getTextColors
getCurrentTextColor
?attr/colorOnSurface
Cursor color N/A (color comes from the theme attr ?attr/colorControlActivated) N/A ?attr/colorPrimary
Text highlight color N/A (color comes from the theme attr ?android:attr/textColorHighlight) N/A @color/m3_highlighted_text

Note: The input text attributes should be set on the TextInputEditText.

Trailing icon attributes

Element Attribute Related method(s) Default value
Mode app:endIconMode setEndIconMode
getEndIconMode
END_ICON_NONE
Color app:endIconTint setEndIconTintList ?attr/colorOnSurfaceVariant (see all states)
Custom icon app:endIconDrawable setEndIconDrawable
getEndIconDrawable
null
Custom icon content description app:endIconContentDescription setEndIconContentDescription
getEndIconContentDescription
null
Custom icon checkable app:endIconCheckable setEndIconCheckable
isEndIconCheckable
true
Error icon app:errorIconDrawable setErrorIconDrawable
getErrorIconDrawable
@drawable/mtrl_ic_error
Error icon color app:errorIconTint setErrorIconTintList ?attr/colorError

Helper/error/counter text attributes

Element Attribute Related method(s) Default value
Helper text enabled app:helperTextEnabled setHelperTextEnabled
isHelperTextEnabled
false
Helper text app:helperText setHelperText
getHelperText
null
Helper text color app:helperTextColor setHelperTextColor
getHelperTextColor
?attr/colorOnSurfaceVariant (see all states)
Helper text typography app:helperTextAppearance setHelperTextAppearance ?attr/textAppearanceBodySmall
Error text enabled app:errorEnabled setErrorEnabled
isErrorEnabled
false
Error text N/A setError
getError
null
Error text accessibility live region app:errorAccessibilityLiveRegion setErrorAccessibilityLiveRegion
getErrorAccessibilityLiveRegion
ViewCompat.ACCESSIBILITY_LIVE_REGION_POLITE
Error text color app:errorTextColor setErrorTextColor
getErrorCurrentTextColors
?attr/colorError
Error text typography app:errorTextAppearance setErrorTextAppearance ?attr/textAppearanceBodySmall
Counter text enabled app:counterEnabled setCounterEnabled
isCounterEnabled
false
Counter text length app:counterMaxLength setCounterMaxLength
getCounterMaxLength
-1
Counter text typography app:counterTextAppearance
app:counterOverflowTextAppearance
setCounterTextAppearance
setCounterOverflowTextAppearance
?attr/textAppearanceBodySmall
Counter text color app:counterTextColor
app:counterOverflowTextColor
setCounterTextColor
setCounterOverflowTextColor
getCounterTextColor
getCounterOverflowTextColor
?attr/colorOnSurfaceVariant (app:counterTextColor) (see all states)
?attr/colorError (app:counterOverflowTextColor)

Prefix/suffix attributes

Element Attribute Related method(s) Default value
Prefix app:prefixText setPrefixText
getPrefixText
null
Prefix color app:prefixTextColor setPrefixTextColor
getPrefixTextColor
?attr/colorOnSurfaceVariant (see all states)
Prefix typography app:prefixTextAppearance setPrefixTextAppearance ?attr/textAppearanceTitleMedium
Suffix app:suffixText setSuffixText
getSuffixText
null
Suffix color app:suffixTextColor setSuffixTextColor
getSuffixTextColor
?attr/colorOnSurfaceVariant (see all states)
Suffix typography app:suffixTextAppearance setSuffixTextAppearance ?attr/textAppearanceTitleMedium

Styles

Element Style Default style theme attribute
Default style Widget.Material3.TextInputLayout.OutlinedBox ?attr/textInputStyle and ?attr/textInputOutlinedStyle
Dense style Widget.Material3.TextInputLayout.OutlinedBox.Dense ?attr/textInputOutlinedDenseStyle
Exposed dropdown menu style Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu ?attr/textInputOutlinedExposedDropdownMenuStyle
Dense exposed dropdown menu style Widget.Material3.TextInputLayout.OutlinedBox.Dense.ExposedDropdownMenu N/A

See the full list of
styles
and
attrs.

Theming text fields

Text fields support
Material Theming which
provides color, typography and shape customization.

Text field theming example

API and source code:

  • TextInputLayout
    • Class definition
    • Class source
  • TextInputEditText
    • Class definition
    • Class source

The following example shows filled and outlined text field types with Material
Theming.

"Filled and outlined text field theming with pink and brown colors and cut corners"

Implementing text field theming

Using theme attributes and styles in res/values/styles.xml adds themes to all
text fields and affects other components:

<style name="Theme.App" parent="Theme.Material3.*">
    ...
    <item name="colorPrimary">@color/shrine_pink_100</item>
    <item name="colorOnSurface">@color/shrine_pink_900</item>
    <item name="colorError">@color/shrine_red</item>
    <item name="textAppearanceTitleMedium">@style/TextAppearance.App.TitleMedium</item>
    <item name="textAppearanceBodySmall">@style/TextAppearance.App.BodySmall</item>
    <item name="shapeAppearanceSmallComponent">@style/ShapeAppearance.App.SmallComponent</item>
</style>

<style name="TextAppearance.App.TitleMedium" parent="TextAppearance.Material3.TitleMedium">
    <item name="fontFamily">@font/rubik</item>
    <item name="android:fontFamily">@font/rubik</item>
</style>

<style name="TextAppearance.App.BodySmall" parent="TextAppearance.Material3.BodySmall">
    <item name="fontFamily">@font/rubik</item>
    <item name="android:fontFamily">@font/rubik</item>
</style>

<style name="ShapeAppearance.App.SmallComponent" parent="ShapeAppearance.Material3.SmallComponent">
    <item name="cornerFamily">cut</item>
    <item name="cornerSize">4dp</item>
</style>

Using default style theme attributes, styles and theme overlays adds themes to
all text fields but does not affect other components:

<style name="Theme.App" parent="Theme.Material3.*">
    ...
    <item name="textInputStyle">@style/Widget.App.TextInputLayout</item>
</style>

<style name="Widget.App.TextInputLayout" parent="Widget.Material3.TextInputLayout.*">
    <item name="materialThemeOverlay">@style/ThemeOverlay.App.TextInputLayout</item>
    <item name="shapeAppearance">@style/ShapeAppearance.App.SmallComponent</item>
    <item name="hintTextColor">?attr/colorOnSurface</item>
</style>

<style name="ThemeOverlay.App.TextInputLayout" parent="">
    <item name="colorPrimary">@color/shrine_pink_100</item>
    <item name="colorOnSurface">@color/shrine_pink_900</item>
    <item name="colorError">@color/shrine_red</item>
    <item name="textAppearanceTitleMedium">@style/TextAppearance.App.TitleMedium</item>
    <item name="textAppearanceBodySmall">@style/TextAppearance.App.BodySmall</item>
    <item name="editTextStyle">@style/Widget.Material3.TextInputEditText.*</item>
</style>

Using the style in the layout affects only this text field:

<com.google.android.material.textfield.TextInputLayout
    ...
    style="@style/Widget.App.TextInputLayout">

    ...

</com.google.android.material.textfield.TextInputLayout>

Note: When setting a materialThemeOverlay on a custom TextInputLayout
style, don’t forget to set editTextStyle to either a
@style/Widget.Material3.TextInputEditText.* style or to a custom one that
inherits from that.
The TextInputLayout styles set
materialThemeOverlay to override editTextStyle with the specific
TextInputEditText style needed. Therefore, you don’t need to specify a style
tag on the edit text.

Содержание

  1. TextInputLayout
  2. Стилизация
  3. Обработка ошибки
  4. Счётчик символов
  5. Создание выпадающего меню
  6. TextInputEditText
  7. TextInputLayout Styling
  8. Hint color
  9. Label, Helper and Error
  10. Fonts
  11. Spaces
  12. Bottom line color
  13. Box background-color
  14. Cursor and Selection
  15. TextInputLayout Styling
  16. Hint color
  17. Label, Helper and Error
  18. Fonts
  19. Spaces
  20. Bottom line color
  21. Box background-color
  22. Cursor and Selection
  23. Валидация элементов формы textInputLayout в Android с помощью связывания данных
  24. Удобный способ валидации форм
  25. Что нам потребуется?
  26. https://github.com/Mustufa786/TextInputLayout-FormValidation

TextInputLayout

Макет TextInputLayout сначала появился в библиотеке Android Design Support Library и добавляет немного красоты к текстовому полю. Когда пользователь начинает вводить текст в текстовом поле, то подсказка, заданная в этом компоненте, всплывает над ним в специальном TextView. Пример можно увидеть на видео.

Библиотека больше не развивается, поэтому используйте AndroidX, которую я и буду теперь использовать в описании.

Компонент можно найти на панели инструментов в разделе Text.

При добавлении компонента через визуальный редактор автоматически добавляется дочерний элемент TextInputEditText.

Так выглядел компонент в составе Support Library.

Подсказку не обязательно указывать в атрибуте android:hint у текстового поля. Можно программно присвоить через метод:

Стилизация

В AndroidX у компонента появились новые стили: OutlinedBox, FilledBox и другие. Можете самостоятельно попробовать пример с двумя стилями и посмотреть на отличия.

Общая стилизация доступна следующим образом. Пропишем стили в styles.xml:

Обработка ошибки

Предыдущий пример показывал применение подсказки. Но также можно выводить сообщения об ошибке. Здесь потребуется написать немного кода. За вывод ошибки отвечает атрибут app:errorEnabled. Назначим текстовому полю тип клавиатуры и однострочный текст. При наборе текста после нажатия на клавишу Enter проверяем длину текста. Если текст меньше четырёх символов, то выводим сообщение об ошибке.

Текст ошибки выводится снизу от текстового поля.

Стиль для сообщения об ошибке можно стилизовать. Добавим новый атрибут.

В файле стилей res/values/styles.xml добавим новый стиль:

Теперь выводится другим цветом.

Расширенный вид стилей:

Применяем через атрибуты app:errorTextAppearance и android:theme.

Счётчик символов

С помощью атрибутов app:counterEnabled и app:counterMaxLength можно установить счётчик символов с указанием предела, который будет выводиться под текстовым полем.

Когда будет превышен лимит, то цвет счётчика изменится. Этот цвет можно стилизовать через стиль.

Стиль применяется к атрибуту app:counterOverflowTextAppearance:

Создание выпадающего меню

Связка TextInputLayout и AutoCompleteTextView позволяет создать выпадающее меню взамен стандартного компонента Spinner. Для этого задействуем один стилей, в котором присутствует ExposedDropdownMenu.

В AutoCompleteTextView установлен тип android:inputType=»none», чтобы у пользователя не было возможности изменять текст. Ведь нам нужно меню, а не текстовое поле.

Для создания элементов меню воспользуемся массивом строк в ресурсах. Добавляем в res/values/strings.xml.

Создадим отдельную разметку для элементов меню в файле res/layout/dropdown_item.xml.

Присоединяем созданный макет к AutoCompleteTextView через адаптер.

Посмотрим на результат. Нажимаем на AutoCompleteTextView и получаем выпадающий список из массива строк.

Мы получили рабочий прототип, но при повороте меню работать не будет. Проверьте самостоятельно. Поэтому немного поправим код.

Можно добавить к элементам меню значок. Заодно добавим подсказку.

TextInputEditText

Казалось бы простой компонент, никаких трудностей не возникает. Но не торопитесь. Стоит повернуть устройство в альбомный режим, как текстовое поле растянется на весь экран и никакой подсказки вы не увидите. Возможно, это баг, который когда-нибудь починят. Но проблему легко решить, если вместо стандартного EditText использовать специальный компонент TextInputEditText:

Источник

TextInputLayout Styling

Today, with the material components, we have at least 3 out of box implementations of input layout: Default, FilledBox, and OutlinedBox. And we want to briefly walk through their styling:

If you are looking for a brief solution you can use this table. Below you can find the description of each of these parameters in detail.

Hint color

Hint color could be set via “android:textColorHint” parameter of TextInputLayout. This parameter also changes the label default color (label focused color could also be changed in other ways). Let’s set a purple color (#673AB7) as an example.

Label, Helper and Error

Such parameters as “app:hintTextAppearance”, “app:helperTextTextAppearance” and “app:errorTextAppearance” together with all the necessary text parameters of styles.xml should be used to customize labels, helpers and errors in TextInputLayout. The parent of the text appearance style should be TextAppearance.AppCompat or some of its children.

Also, please keep in mind the following:

  • “ app:hintTextAppearance” affects the focused label color and label size in any state;
  • when an error is shown, the bottom/border line will have the color indicated in the “android:textColor” parameter of errorTextAppearance. This color will be changed to the default once the error is removed.

Here is the TextAppearances for error and helper that was used in the above shown TextInputLayouts:

Fonts

Fonts of all elements except inputted text (label, hint, error, and helper) could be easily changed in the program via the typeface parameter of TextInputLayout. We have done it in the following way:

Spaces

Label’s, Helper’s and Error’s spaces are connected to the EditText in the TextInputLayout. So, to increase or decrease spaces between the error/helper messages and bottom line/border you should use “android:layout_marginBottom” parameter, between the label and the top of the text, or add some space on the start of the error, helper and the label, and you should set positive or negative padding to the EditText. But you should understand that this will affect the text inside the InputLayout so, it would be better if horizontal spaces were symmetric from both sides.

As an example, let’s increase space above the errors for Default and OutlinedBox input layouts and decrease for FilledBox input layout. Also, let’s add some extra space at the start of the input layouts.

Bottom line color

Bottom line color could be changed with “app:backgroundTint” attribute of EditText view. Pay attention to the prefix, “app:” that makes this parameter back-compatible and useful even for Android API 16.

As for the OutlinedBox, it does not have the bottom line but has an outline instead. To change its color we should use “app:boxStrokeColor” parameter, but this parameter changes stroke color in the focused state only. Changing the default state of the stroke is a bit tricky. We should override mtrl_textinput_default_box_stroke_color color. The line below should be added to the color.xml file:

Let’s make the bottom line and the outline stroke color purple (#673AB7) as well.

Box background-color

This element is present in Filled and Outlined input layouts and can be changed via “app:boxBackgroundColor” parameter. Let’s change this parameter to the transparent purple (#26673AB7) only for FilledBox input layout.

Cursor and Selection

Finally, we get to the most interesting part — how to change the cursor and the selection handles. Most of you have already tried to use “app:textSelectHandle” parameters, that allow changing the drawable of the cursor handle and selection left and right handles. But how to change the color without drawing custom drawables and without changing the main application colors? It is not the secret that the cursor and handles color, as well as label color in focus mode, take their color from the AppTheme “colorAccent”. Of course, we can change it for the whole project but it is not obligatory. We can just use ThemeOverlay and change the “colorAccent” for a single view. We should inherit our style from ThemeOverlay.AppCompat and set it as the “android:theme” parameter of the view and that is all. As for the selection highlight, you can change it via android:textColorHighlight of the EditText.

In the example above was used android:color/holo_blue_light:

So, my final layout looked like this:

colors.xml includes the following colors:

styles.xml includes the following styles:

Tap the 👏 button if you found this article useful!

About the Author
Dmytro is Android Developer at OmiSoft, whose inner perfectionist does not allow to be content with mediocre results but forces him to move forward to excellence.

Need an Android mobile app with clean & maintainable code? Click here to get an estimate! Or find us on Facebook and Twitter.

Источник

TextInputLayout Styling

Today, with the material components, we have at least 3 out of box implementations of input layout: Default, FilledBox, and OutlinedBox. And we want to briefly walk through their styling:

If you are looking for a brief solution you can use this table. Below you can find the description of each of these parameters in detail.

Hint color

Hint color could be set via “android:textColorHint” parameter of TextInputLayout. This parameter also changes the label default color (label focused color could also be changed in other ways). Let’s set a purple color (#673AB7) as an example.

Label, Helper and Error

Such parameters as “app:hintTextAppearance”, “app:helperTextTextAppearance” and “app:errorTextAppearance” together with all the necessary text parameters of styles.xml should be used to customize labels, helpers and errors in TextInputLayout. The parent of the text appearance style should be TextAppearance.AppCompat or some of its children.

Also, please keep in mind the following:

  • “ app:hintTextAppearance” affects the focused label color and label size in any state;
  • when an error is shown, the bottom/border line will have the color indicated in the “android:textColor” parameter of errorTextAppearance. This color will be changed to the default once the error is removed.

Here is the TextAppearances for error and helper that was used in the above shown TextInputLayouts:

Fonts

Fonts of all elements except inputted text (label, hint, error, and helper) could be easily changed in the program via the typeface parameter of TextInputLayout. We have done it in the following way:

Spaces

Label’s, Helper’s and Error’s spaces are connected to the EditText in the TextInputLayout. So, to increase or decrease spaces between the error/helper messages and bottom line/border you should use “android:layout_marginBottom” parameter, between the label and the top of the text, or add some space on the start of the error, helper and the label, and you should set positive or negative padding to the EditText. But you should understand that this will affect the text inside the InputLayout so, it would be better if horizontal spaces were symmetric from both sides.

As an example, let’s increase space above the errors for Default and OutlinedBox input layouts and decrease for FilledBox input layout. Also, let’s add some extra space at the start of the input layouts.

Bottom line color

Bottom line color could be changed with “app:backgroundTint” attribute of EditText view. Pay attention to the prefix, “app:” that makes this parameter back-compatible and useful even for Android API 16.

As for the OutlinedBox, it does not have the bottom line but has an outline instead. To change its color we should use “app:boxStrokeColor” parameter, but this parameter changes stroke color in the focused state only. Changing the default state of the stroke is a bit tricky. We should override mtrl_textinput_default_box_stroke_color color. The line below should be added to the color.xml file:

Let’s make the bottom line and the outline stroke color purple (#673AB7) as well.

Box background-color

This element is present in Filled and Outlined input layouts and can be changed via “app:boxBackgroundColor” parameter. Let’s change this parameter to the transparent purple (#26673AB7) only for FilledBox input layout.

Cursor and Selection

Finally, we get to the most interesting part — how to change the cursor and the selection handles. Most of you have already tried to use “app:textSelectHandle” parameters, that allow changing the drawable of the cursor handle and selection left and right handles. But how to change the color without drawing custom drawables and without changing the main application colors? It is not the secret that the cursor and handles color, as well as label color in focus mode, take their color from the AppTheme “colorAccent”. Of course, we can change it for the whole project but it is not obligatory. We can just use ThemeOverlay and change the “colorAccent” for a single view. We should inherit our style from ThemeOverlay.AppCompat and set it as the “android:theme” parameter of the view and that is all. As for the selection highlight, you can change it via android:textColorHighlight of the EditText.

In the example above was used android:color/holo_blue_light:

So, my final layout looked like this:

colors.xml includes the following colors:

styles.xml includes the following styles:

Tap the 👏 button if you found this article useful!

About the Author
Dmytro is Android Developer at OmiSoft, whose inner perfectionist does not allow to be content with mediocre results but forces him to move forward to excellence.

Need an Android mobile app with clean & maintainable code? Click here to get an estimate! Or find us on Facebook and Twitter.

Источник

Валидация элементов формы textInputLayout в Android с помощью связывания данных

Удобный способ валидации форм

«Чтобы научиться чему-то хорошо, нужно научиться делать это несколькими способами».

Несколько дней назад я работал над проектом, где мне нужно было реализовать валидацию элементов формы textInputLayout и textInputEditText с помощью связывания данных. К сожалению, доступно не так много документации на эту тему.

В конце концов я добился желаемого результата, изучив кое-какие материалы и проведя ряд экспериментов. Вот что я хотел получить:

Финальный вид приложения

Уверен, что многие разработчики хотели бы реализовать такой же функционал и удобное взаимодействие с формами. Итак, давайте начнем.

Что нам потребуется?

Я разобью проект на этапы, чтобы легче было понять, что мы делаем.

1. Настроим исходный проект и включим связывание данных в файле build.gradle(:app) , добавив под тег android<> следующую строку:

Для использования элементов textInputLayout и textInputEditText необходимо включить поддержку Material для Android, добавив в файл build.gradle(:app) следующую зависимость:

Создадим макет нашей формы. Я сделаю простой макет, потому что моя цель — определить его основной функционал, а не создать хороший дизайн.

Я создал вот такой простой макет:

Вот содержимое файла activity_main.xml :

Если вас смущают теги , не переживайте — о них я написал в своей предыдущей статье.

Наш макет готов. Теперь займемся кодом.

2. На GIF-анимации, показывающей поведение финального варианта приложения (см. выше), видно, как появляются и исчезают сообщения об ошибках, когда заданные условия принимают значение true. Это происходит потому, что я связал каждое текстовое поле с объектом TextWatcher, к которому постоянно происходит обращение по мере ввода текста пользователем.

В файле MainActivity.kt я создал класс, который унаследован от класса TextWatcher :

Параметр view , который передается в конструктор класса, я опишу позже.

3. Это основная часть. У каждого текстового поля имеется ряд условий, которые должны иметь значение true перед отправкой данных формы. Код, задающий условия для каждого текстового поля, представлен ниже:

4. Теперь необходимо связать каждое текстовое поле с классом textWatcher , который был создан ранее:

Но как класс TextFieldValidation узнает, с каким текстовым полем нужно связываться? Прокрутив статью выше, вы увидите, что я добавил следующий комментарий в один из методов класса TextFieldValidation :

Обратите внимание, что я передаю параметр view в конструктор класса TextFieldValidation , который отвечает за разделение каждого текстового поля и применение каждого из указанных выше методов следующим образом:

Финальный вариант файла MainActivity.kt выглядит так:

Запустим приложение и полюбуемся поведением формы ввода:

Полный исходный код этого проекта можно скачать по ссылке ниже:

https://github.com/Mustufa786/TextInputLayout-FormValidation

Надеюсь, вы узнали из этой статьи что-то новое для себя. Следите за появлением новых статей! Успехов в разработке!

Источник

Introduction

TextInputLayout was introduced to display the floating label on EditText. The EditText has to be wrapped by TextInputLayout in order to display the floating label.

TextInputLayout is a layout which wraps an EditText (or descendant) to show a floating label when the hint is hidden due to the user inputting text. Additonally the TextInputLayout enables you to display an error message below the EditText.

Make sure the following dependency is added to your app’s build.gradle file under dependencies:

compile 'com.android.support:design:25.3.1'

Basic usage

It is the basic usage of the TextInputLayout.
Make sure to add the dependency in the build.gradle file as described in the remarks section.

Example:

 <android.support.design.widget.TextInputLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content">

     <EditText
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:hint="@string/username"/>
 
 </android.support.design.widget.TextInputLayout>

Handling Errors

You can use the TextInputLayout to display error messages according to the material design guidelines using the setError and setErrorEnabledmethods.

In order to show the error below the EditText use:

TextInputLayout til = (TextInputLayout) findViewById(R.id.username);
til.setErrorEnabled(true);
til.setError("You need to enter a name");

To enable error in the TextInputLayout you can eithr use app:errorEnabled="true" in xml or til.setErrorEnabled(true); as shown above.

You will obtain:

enter image description here

Adding Character Counting

The TextInputLayout has a character counter for an EditText defined within it.
The counter will be rendered below the EditText.

Just use the setCounterEnabled() and setCounterMaxLength methods:

TextInputLayout til = (TextInputLayout) findViewById(R.id.username);
til.setCounterEnabled(true);
til.setCounterMaxLength(15);

or the app:counterEnabled and app:counterMaxLength attributes in the xml.

<android.support.design.widget.TextInputLayout
    app:counterEnabled="true"
    app:counterMaxLength="15">

    <EditText/>

</android.support.design.widget.TextInputLayout>

Password Visibility Toggles

With an input password type, you can also enable an icon that can show or hide the entire text using the passwordToggleEnabled attribute.

You can also customize same default using these attributes:

  • passwordToggleDrawable: to change the default eye icon
  • passwordToggleTint: to apply a tint to the password visibility toggle drawable.
  • passwordToggleTintMode: to specify the blending mode used to apply the background tint.

Example:

<android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:passwordToggleContentDescription="@string/description"
        app:passwordToggleDrawable="@drawable/another_toggle_drawable"
        app:passwordToggleEnabled="true">

            <EditText/>

</android.support.design.widget.TextInputLayout>

TextInputEditText

The TextInputEditText is an EditText with an extra fix to display a hint in the IME when in ‘extract’ mode.

The Extract mode is the mode that the keyboard editor switches to when you click on an EditText when the space is too small (for example landscape on a smartphone).
In this case, using an EditText while you are editing the text you can see that the IME doesn’t give you a hint of what you’re editing

The TextInputEditText fixes this issue providing hint text while the user’s device’s IME is in Extract mode.

Example:

<android.support.design.widget.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Description"
    >
    <android.support.design.widget.TextInputEditText
        android:id="@+id/description"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</android.support.design.widget.TextInputLayout>

Customizing the appearance of the TextInputLayout

You can customize the appearance of the TextInputLayout and its embedded EditTextby defining custom styles in your styles.xml. The defined styles can either be added as styles or themes to your TextInputLayout.

Example for customizing the hint appearance:

styles.xml:

<!--Floating label text style-->  
<style name="MyHintStyle" parent="TextAppearance.AppCompat.Small">  
    <item name="android:textColor">@color/black</item>
</style>

<!--Input field style-->  
<style name="MyEditText" parent="Theme.AppCompat.Light">  
    <item name="colorControlNormal">@color/indigo</item>
    <item name="colorControlActivated">@color/pink</item>
</style>  

To Apply Style update your TextInputLayout And EditText as follows

<android.support.design.widget.TextInputLayout  
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:hintTextAppearance="@style/MyHintStyle">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/Title"
        android:theme="@style/MyEditText" />

</android.support.design.widget.TextInputLayout>  

Example to customize the accent color of the TextInputLayout. The accent color affects the color of the baseline of the EditText and the text color for the floating hint text:

styles.xml:

<style name="TextInputLayoutWithPrimaryColor" parent="Widget.Design.TextInputLayout">
    <item name="colorAccent">@color/primary</item>
</style> 

layout file:

<android.support.design.widget.TextInputLayout
            android:id="@+id/textInputLayout_password"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/TextInputLayoutWithPrimaryColor">

            <android.support.design.widget.TextInputEditText
                android:id="@+id/textInputEditText_password"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/login_hint_password"
                android:inputType="textPassword" />

</android.support.design.widget.TextInputLayout>

Понравилась статья? Поделить с друзьями:
  • Test completed successfully without error punkbuster
  • Test completed successfully without error battlefield
  • Temporary server error prx2
  • Test c 1 10 fatal error freeimage h no such file or directory
  • Temporary server error please try again later prx5