0

我想制作一个 EditText,当满足“错误”条件时,其文本变为红色。我知道 TextInputLayout 有一个内置的错误状态,但我不想在输入区域下面有文本,我不想在我的项目中包含支持设计库(这是一个 sdk - 所以其他人将包括它)。但是,我的 EditText总是显示错误状态,我不知道为什么。

到目前为止我的努力:

首先,我声明一个可样式化的东西。看起来不错。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MySpecialEditText">
        <attr name="state_error" format="boolean"/>
    </declare-styleable>
</resources>

然后我在我的res/colors目录中创建一个选择器。现在,如果设置了我的特殊属性,我真的更喜欢只覆盖颜色。但是,如果我必须复制android:state-pressed等 状态及其每个组合,我可以这样做(并且具有相同的结果,请参见下文)。这个文件是res/color/red_on_error_dark.xml.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:custom="http://schemas.android.com/apk/lib/com.mypackage">
    <item
        custom:state_error="true"
        android:color="#f00" />
    <item
        custom:state_error="false"
        android:color="@android:color/primary_text_dark"/>
    <item android:color="@android:color/primary_text_dark"/>
</selector>

然后我将我的新时尚事物添加到我的自定义类的 XML 包含中:

<com.mypackage.MySpecialEditText
     android:id="@+id/some_id"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:background="@android:color/transparent"
     android:hint="@string/a_nice_hint"
     android:inputType="number"
     android:textColor="@color/red_on_error_dark"
     />

到目前为止,一切都很好。现在,我创建了扩展 EditText 的类:

public class MySpecialEditText extends EditText {

    private static final int[] STATE_ERROR = {R.attr.state_error};
    private boolean mStateError;
    //... lots of other fun functionality

    // Time to set my custom status
    public void setStateError(boolean stateError) {
        mStateError = stateError;
        invalidate();
        refreshDrawableState();
    }

    // And now, I need to add the custom state drawable.
    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
        if (mStateError) {    
            mergeDrawableStates(drawableState, STATE_ERROR);
        } 
        return drawableState;
    }
}

所有这些都很容易组合在一起。但是,当我运行代码时,它总是将文本绘制为红色。

我已经验证的事情:

  1. 我正确设置了错误/无错误状态。
  2. onCreateDrawableState代码在非错误时间内通过该方法!它跳过mergeDrawableStates具有额外属性的方法。(我还添加了一个else子句并返回了一个没有添加额外空格的 drawableState)。
  3. 即使该属性是布尔值,并且理论上应该能够接受 true 或 false 的值,我还是添加了一个单独的 attr STATE_VALID,并将我的选择器更改为如下。

我什至将选择器更改为详尽无遗:

<item custom:state_error="true" android:state_selected="true" android:color="#f00" />
<item custom:state_error="true" android:state_focused="true" android:color="#f00" />
<item custom:state_error="true" android:state_pressed="true" android:color="#f00" />

<item custom:state_error="false" android:state_selected="true" android:color="@android:color/primary_text_dark" />
<item custom:state_error="false" android:state_focused="true" android:color="@android:color/primary_text_dark" />
<item custom:state_error="false" android:state_pressed="true" android:color="@android:color/primary_text_dark" />

而且我走得更远,将不必要的额外状态与一堆 结合起来android:state_blah,所以我的选择器中有 20 种不同的情况。(实际上,在这种情况下,它总是保持白色,也好不了多少)。

现在,我真正非常喜欢的是声明一个可样式化的值,其他人(使用我的 sdk)可以设置一个值,如果他们愿意的话。但是现在我很高兴知道为什么文本总是红色的。

编辑:一个完全合法的解决方法是当我在MySpecialEditText. 这是我的临时解决方案,但它阻止了某人使用我的控件并custom:state_error=@color/some_custom_color在他们选择的主题中添加一个 或类似的值。只要我手动调用 setTextColor,错误颜色总是我特定的红色阴影。

我可以更进一步,为错误颜色添加一个新的构造函数或设置器,但这对于库来说不是一个很好的解决方案。如果您使用该库并实例化我的控件,它将获取EditText您已经拥有的所有样式,因此它看起来很原生。如果您想自定义错误颜色,我希望您能够在一个地方为您的整个应用程序执行此操作,其中包含一段可以由设计人员运行的漂亮 XML。

有任何想法吗?先发制人地感谢所有回答者和尝试回答者。

4

0 回答 0