无法在TextInputLayout内的EditText中使用可绘制对象。

6

我最近将Android Design库从24.2.1升级到25.0.0。此后,EditText中的“drawableX”功能不起作用。

编辑01.11: 我了解到,如果您使用android:drawableStart而不是android:drawableLeft,则可以在xml中设置drawable。但是,以编程方式设置可绘制物不起作用。我使用此功能使“清除”按钮清空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]);
}
5个回答

28

这是我能找到的最简单的方法:

步骤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 */);

有关自定义和其他功能的详细信息,请查看此链接。干杯!


1
给你的"It's important to know that it will not show if you don't set the endIconMode."这句话点个赞。 - YUSMLE
1
很棒的答案!完美运作。 - DIRTY DAVE

7

我曾经遇到过完全相同的问题,我所做的就是在drawableLeft之外再添加一个drawableStart,这样它就会如预期般显示。


是的,很奇怪,drawableLeft不应该依赖于drawableStart,可能是一个bug。 - Ahmed Ashraf
但我的真正问题是,我想以编程的方式执行它,就像在有文本或没有文本时显示和隐藏清除图标一样。我使用setCompoundDrawables(),但这什么也没显示出来(之前它可以)。 - Gober
修改了问题以反映我的真实问题。 - Gober
啊哈,这看起来很有趣,我要进一步调查一下,因为我以前从未尝试过以编程方式更改它。 - Ahmed Ashraf
我根据你的答案找到了“解决方案”,并在另一个回答中发布了它。 - Gober
3
左侧正常工作,但右侧出现问题,我已经添加了drawableRight和drawableEnd,但图标仍然没有显示。 - Chandrahasan

3

为 TextInputLayout 添加 endIconMode 属性以添加可绘制的末尾图标。

<com.google.android.material.textfield.TextInputLayout
   app:endIconMode="custom"
   app:endIconDrawable="@drawable/ic_tick_grey"
   ....
</com.google.android.material.textfield.TextInputLayout>

1
根据 Ahmed Ashraf G 的回答,我成功找到了解决方案。 将以下代码进行更改:
setCompoundDrawables(getCompoundDrawables()[0],
        getCompoundDrawables()[1], icon, getCompoundDrawables()[3]);

至:

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

来自StackOverflow其他地方的信息(文档中没有提到),xxxCompoundDrawablesXxx和xxxCompundDrawablesRelativeXxx之间的区别在于相对版本考虑RTL语言,即它们与使用drawableStart而不是drawableLeft相同。

因此,总的来说,Google已经破坏了TextInputLayout内EditText的所有非RTL方法。由于这些新方法是在API级别17中添加的,我认为这是一个重大的错误,可能会在未来的更新中得到修复。


我知道这是很久的问题,但有没有一种方法可以在编辑文本的末尾设置两个可绘制的对象? - Wellington Yogui

0

尝试将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>

这会产生以下错误:TextInputEditText元素不允许在此处。同时,在xml中,Ahmed Ashraf提供的解决方案可行(使用drawableStart)。 - Gober

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接