Невозможно использовать возможность рисования в EditText внутри TextInputLayout

Недавно я обновил библиотеку Android Design с 24.2.1 до 25.0.0. После этого функция «drawableX» в EditText не работает.

РЕДАКТИРОВАТЬ 01.11: я узнал, что настройка drawable в xml работает, если вы используете android:drawableStart вместо android:drawableLeft. Но программная установка рисунков не работает. Я использую это, чтобы сделать кнопку «Очистить», чтобы очистить EditText. Но сейчас эта функция сломана. Я был бы признателен за любые обходные пути или информацию о том, преднамеренно ли это от Google или ошибка!

Мой код для Clearable edit-text, который работал раньше, но не работает сейчас:

public class ClearableErrorTextInputEditText extends ErrorTextInputEditText implements View.OnFocusChangeListener, View.OnTouchListener, TextWatcher {

private Drawable resIcon;
private OnFocusChangeListener childFocusListener;

public ClearableErrorTextInputEditText(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    setup();
}

public ClearableErrorTextInputEditText(Context context, AttributeSet attrs) {
    super(context, attrs);
    setup();
}

public ClearableErrorTextInputEditText(Context context) {
    super(context);
    setup();
}

@Override
public boolean onTouch(View v, MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_UP) {
        if (getCompoundDrawables()[2] != null) {
            final boolean tappedClose = event.getX() > (getWidth() - getPaddingRight() - resIcon.getIntrinsicWidth());
            if (tappedClose) {
                setText("");
                return false; // true will fail on emulator running 2.1 and physical keyboard / scroll wheel
            }
        }
    }
    return false;
}

@Override
public void setOnFocusChangeListener(OnFocusChangeListener l) {
    childFocusListener = l;
}

@Override
public void onFocusChange(View v, boolean hasFocus) {
    setClearIconVisible(hasFocus && getText().length() > 0);

    if (childFocusListener!=null){
        childFocusListener.onFocusChange(v, hasFocus);
    }
}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count){
    super.onTextChanged(s, start, before, count);
    setClearIconVisible(isFocused() && s.length() > 0);
}

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {} // not interesting

@Override
public void afterTextChanged(Editable s) {} //  // not interesting

private void setup() {
    if(isInEditMode()){
        return;
    }

    resIcon = getResources().getDrawable(R.drawable.ic_clear, null);
    resIcon.setBounds(0, 0, resIcon.getIntrinsicWidth(), resIcon.getIntrinsicHeight());

    setClearIconVisible(false);

    super.setOnTouchListener(this);
    super.setOnFocusChangeListener(this);
    addTextChangedListener(this);
}

private void setClearIconVisible(final boolean visible){
    final Drawable icon = visible ? resIcon : null;
    setCompoundDrawables(getCompoundDrawables()[0],
            getCompoundDrawables()[1], icon, getCompoundDrawables()[3]);
}

person Gober    schedule 01.11.2016    source источник


Ответы (5)


Это самый простой способ, который я мог найти:

Шаг 1.

В своем макете установите свой endIconDrawable. Важно знать, что он не будет отображаться, если вы не установите endIconMode< /сильный>.

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/custom_end_icon"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="@string/hint_text"
    app:endIconMode="custom"
    app:endIconDrawable="@drawable/custom_icon"
    app:endIconContentDescription="@string/custom_content_desc">

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

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

Шаг 2. В зависимости от того, что вы хотите сделать с кнопкой, есть три метода, которые вы можете вызвать для нее.

TextInputLayout textInputCustomEndIcon = view.findViewById(R.id.custom_end_icon);

// If the icon should work as button, set an OnClickListener to it.
textInputCustomEndIcon
    .setEndIconOnClickListener(/* custom OnClickListener */);

// If any specific changes should be done when the EditText is attached (and
// thus when the end icon is added to it), set an OnEditTextAttachedListener
textInputCustomEndIcon
    .addOnEditTextAttachedListener(/* custom OnEditTextAttachedListener */);

// If any specific changes should be done if/when the endIconMode gets changed,
// set an OnEndIconChangedListener
textInputCustomEndIcon
    .addOnEndIconChangedListener(/* custom OnEndIconChangedListener */);

Чтобы узнать больше о настройке и дополнительных функциях, перейдите по этой ссылке.

person Doilio Matsinhe    schedule 26.07.2019
comment
Проголосуйте за ваш. Важно знать, что он не будет отображаться, если вы не установите endIconMode. приговор. - person YUSMLE; 13.10.2020
comment
Спасибо @YUSMLE - person Doilio Matsinhe; 04.12.2020

У меня была точно такая же проблема. Все, что я сделал, это добавил drawableStart вместе с drawableLeft, и он отображается, как и ожидалось.

person Ahmed Ashraf    schedule 01.11.2016
comment
Да, это странно, но drawableLeft не должен зависеть от drawableStart, возможно, это ошибка. - person Ahmed Ashraf; 01.11.2016
comment
Но моя настоящая проблема в том, что я хочу сделать это программно, так как я показываю и скрываю значок очистки, если есть текст или нет. Я использую setCompoundDrawables(), и это ничего не показывает (раньше это было) - person Gober; 01.11.2016
comment
Изменил вопрос, чтобы отразить мою реальную проблему - person Gober; 01.11.2016
comment
ага, это выглядит интересно, я собираюсь исследовать это дальше, так как я не пытался изменить это программно раньше - person Ahmed Ashraf; 01.11.2016
comment
Я нашел решение, основанное на вашем ответе. Опубликовал это в другом ответе - person Gober; 02.11.2016
comment
Левая сторона работает нормально, но тот же случай не работает для правой стороны, я добавил drawableRight с drawableEnd, но значок все еще не отображается - person Chandrahasan; 11.05.2017

Добавьте endIconMode в Custom для добавления выводимого конца для textinputlayout.

<com.google.android.material.textfield.TextInputLayout
   app:endIconMode="custom"
   app:endIconDrawable="@drawable/ic_tick_grey"
   ....
</com.google.android.material.textfield.TextInputLayout>
person Dino Sunny    schedule 19.06.2020
comment
Спасибо за ответ :) - person Detoxic Spirit; 17.05.2021

Основываясь на ответе Ахмеда Ашрафа Г., я смог найти решение. Изменение следующего кода:

setCompoundDrawables(getCompoundDrawables()[0],
        getCompoundDrawables()[1], icon, getCompoundDrawables()[3]);

to:

setCompoundDrawablesRelative(getCompoundDrawablesRelative()[0],
            getCompoundDrawablesRelative()[1], icon, getCompoundDrawablesRelative()[3]);

Из других мест на StackOverflow (в документации об этом НЕ упоминается) разница между xxxCompoundDrawablesXxx и xxxCompundDrawablesRelativeXxx заключается в том, что относительные версии учитывают RTL-языки, т.е. они аналогичны использованию drawableStart вместо drawableLeft.

Итак, в заключение, Google сломал все методы, которые не являются RTL-методами для EditText внутри TextInputLayout. Поскольку новые методы добавляются на уровне API 17, я считаю это серьезной ошибкой, которая, вероятно, будет исправлена ​​​​в будущих обновлениях.

person Gober    schedule 02.11.2016
comment
Я знаю, что это долго, но есть ли способ установить два чертежа в конце текста редактирования? - person Wellington Yogui; 11.11.2019

попробуйте заменить EditText на android.support.design.widget.TextInputEditText, например:

 <android.support.design.widget.TextInputLayout
     android:id="@+id/email_input"
     android:layout_width="match_parent"
     android:layout_height="wrap_content">

 <android.support.design.widget.TextInputEditText
          android:id="@+id/email"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:hint="@string/email_hint"
          android:drawableStart="@drawable/ic_clear" />
 </android.support.design.widget.TextInputLayout>
person Vladimir Salguero    schedule 01.11.2016
comment
Это дает следующую ошибку: Элемент TextInputEditText здесь не разрешен. Также в xml работает решение, данное Ахмедом Ашрафом (используйте drawableStart). - person Gober; 02.11.2016