如何使用自定义属性(如错误)设置EditText的颜色?

时间:2017-01-23 21:45:39

标签: android android-edittext android-custom-view textcolor declare-styleable

我想创建一个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方法!它使用extra属性跳过mergeDrawableStates方法。 (我还添加了一个else子句并返回了一个没有添加额外空格的drawableState。)
  3. 即使该属性是boolean,理论上应该能够接受true或false的值,我还添加了一个单独的attr STATE_VALID,并将我的选择器更改为如下所示。 / p>

                  

  4. 我甚至将选择器更改为详尽无遗:

    <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中达到错误状态时,一个完全合法的解决方法就是调用setTextColor。这是我的临时解决方案,但它阻止某人使用我的控件并在他们选择的主题中添加custom:state_error=@color/some_custom_color或类似值。只要我手动调用setTextColor,错误颜色总是我特别的红色阴影。

    我可以更进一步为错误颜色添加新的构造函数或setter,但这对于库来说不是一个非常好的解决方案。如果您使用该库并实例化我的控件,它将获取您已有的所有EditText样式,因此它看起来是原生的。如果你想自定义错误颜色,我希望你能够在一个地方为你的整个应用程序做一个你可以由设计师运行的一个很好的XML。

    有什么想法吗?先发制人,谢谢所有回答者和未遂的回答者。

0 个答案:

没有答案