TextInputLayout: различный цвет для метки подсказки, когда не сфокусирован

Что я хочу сделать:

При использовании EditText, встроенного в TextInputLayout, я хочу …

  1. Установите цвет метки на ЗЕЛЕНЫЙ, когда он дефокусирован и плавает над EditText, потому что пользователь уже ввел некоторое значение
  2. Установите цвет ярлыка на RED, когда он дефокусирован и находится внутри EditText, потому что пользователь еще не ввел значение
  3. Я не хочу менять цвет текста подсказки всех моих EditTexts на RED, но только когда они завернуты в TextInputLayout (мне не нужен общий подход – конкретный подход, например, установка темы / стиля для каждого TextInputLayout в Макет XML будет в порядке)
  4. Сохраните (то есть не меняйте) цвет акцента (ЖЕЛТЫЙ), используемый для окраски плавающей метки, когда пользователь сфокусировал поле.

То, что я пробовал:

Установка ниже в качестве темы / стиля в TextInputLayout выполняется 1, но не 2.

<style name="FloatingLabel" parent="Widget.Design.TextInputLayout"> <item name="android:textColorHint">@color/red</item> </style> 

Установка определенного цвета в моем встроенном EditText, который изменяет текст подсказки на другой цвет:

  android:textColorHint="@color/text_placeholder_gray" 

На самом деле вызывает перекрытие текстов подсказок, когда метка перемещается из ее плавающего положения обратно в Edittext в качестве подсказки (то есть без текста).

Установка этого параметра:

 <style name="TextAppearence.App.TextInputLayout" parent="@android:style/TextAppearance"> <item name="android:textColor">@color/main_color</item> 

На TextInputLayout:

  <android.support.design.widget.TextInputLayout ... app:hintTextAppearance="@style/TextAppearence.App.TextInputLayout" > 

Изменяет цвет метки подсказки, но также делает это для сфокусированного состояния – что означает, что 4 не выполняется.

А поскольку картинка говорит больше, чем слова tousand (все поля находятся в нефокусированном состоянии):

Введите описание изображения здесь

Как достичь настройки, которая удовлетворяет критериям 1-4?

    У меня была аналогичная проблема: мне нужно было реализовать макет ввода текста, в котором ярлык имеет разные цвета для пустого (когда текст текста не вводится в текст редактирования), «заполнено» и сфокусировано. Моя основная проблема заключалась в том, как различать пустое и заполненное состояние, так как установка другого цвета для сфокусированного состояния была уже простой с использованием селекторов. В конце концов я решил определить пользовательское состояние «пустой текст» и реализовать свой собственный макет ввода текста (который расширяет стандартный макет ввода текста).

    Вот какой код:

    В res / values ​​/ attrs.xml:

     <?xml version="1.0" encoding="utf-8"?> <resources> ... <!-- Custom state for the text input layout to determine whether the label is shown above some text or not --> <declare-styleable name="EmptyTextState"> <attr name="state_empty_text" format="boolean"/> </declare-styleable> </resources> 

    Пользовательский макет ввода текста:

     public class EmptyStateTextInputLayout extends TextInputLayout { private boolean emptyText = true; private static final int[] EMPTY_TEXT_STATE = new int[]{R.attr.state_empty_text}; public EmptyStateTextInputLayout(Context context) { super(context); } public EmptyStateTextInputLayout(Context context, AttributeSet attrs) { super(context, attrs); } public EmptyStateTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected int[] onCreateDrawableState(int extraSpace) { int[] state = super.onCreateDrawableState(extraSpace + 1); if (emptyText) { mergeDrawableStates(state, EMPTY_TEXT_STATE); } return state; } public void setEmptyTextState(boolean emptyTextState) { this.emptyText = emptyTextState; refreshDrawableState(); } @Override public void addView(View child, int index, ViewGroup.LayoutParams params) { if (child instanceof EditText) { EditText editText = (EditText) child; if (!TextUtils.isEmpty(editText.getText())) { setEmptyTextState(false); } editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void afterTextChanged(Editable editable) { if (!TextUtils.isEmpty(editable)) { setEmptyTextState(false); } else { setEmptyTextState(true); } } }); } super.addView(child, index, params); } } 

    Селектор XML для установки цвета метки в разных состояниях (res / color / input_field_floating_label.xml):

     <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:color="@color/focused_text_color" android:state_focused="true" /> <item android:color="@color/placeholder_color" app:state_empty_text="true"/> <item android:color="@color/primary_text_color"/> <!-- default color --> </selector> 

    Стиль для ввода текста (в res / values ​​/ styles.xml):

     <style name="EditTextLayout"> ... <item name="android:textColorHint">@color/input_field_floating_label</item> </style> 

    Тема и стиль для текста редактирования (все еще в res / values ​​/ styles.xml):

     <style name="EditTextTheme"> ... <item name="android:textColorHint">@color/input_field_floating_label</item> </style> <style name="EditText"> <item name="android:theme">@style/EditTextTheme</item> ... </style> 

    Применение:

     <com.package.path.widget.EmptyStateTextInputLayout style="@style/DarkEditTextLayout" android:layout_height="wrap_content" android:layout_width="match_parent" ... > <EditText style="@style/EditText" android:layout_width="match_parent" android:layout_height="wrap_content" /> </com.package.path.widget.EmptyStateTextInputLayout> 

    Я рекомендую это сообщение в блоге, чтобы получить представление о работе с пользовательскими состояниями: http://code.neenbedankt.com/example-of-custom-states-in-android-components/