我想制作一个 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;
}
}
所有这些都很容易组合在一起。但是,当我运行代码时,它总是将文本绘制为红色。
我已经验证的事情:
- 我正确设置了错误/无错误状态。
onCreateDrawableState
代码在非错误时间内通过该方法!它跳过mergeDrawableStates
具有额外属性的方法。(我还添加了一个else
子句并返回了一个没有添加额外空格的 drawableState)。即使该属性是布尔值,并且理论上应该能够接受 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。
有任何想法吗?先发制人地感谢所有回答者和尝试回答者。