我在Fragment
内有一个ViewPager
。
在该片段中,我有几个EditText
的OnTextChanged侦听器(在onViewCreated
方法中添加)执行一些验证工作并调用函数来设置/删除错误,例如:
// Sets or removes an error message in the nameField EditText
public void validateUsername(String message)
{
if(message == null)
{
nameField.setError(null);
}
else
{
nameField.setError(message,errorIcon);
}
}
errorIcon是Drawable
instanciated onCreate
,如下所示:
errorIcon = getResources().getDrawable(R.drawable.ic_wrong_input);
errorIcon.setBounds(new Rect(0, 0, errorIcon.getIntrinsicWidth(), errorIcon.getIntrinsicHeight()));
当我在EditText中输入内容时,验证工作正常:显示我的错误消息,带有我的自定义图标。
但是当我旋转设备时,validateUsername()
函数被调用(预期行为),nameField.setError(message,errorIcon)
分支中的else
被执行但EditText
获得Android的默认值错误图标而不是我的(是的,调试时我可以看到我的errorIcon Drawable是实例化的)。之后,如果我在EditText
中输入无效的内容,则会再次调用验证方法,这次我再次获得自定义错误图标。如果我再次旋转设备,同样的事情:重新创建默认图标,输入无效后自定义图标...
任何人都可以解释这种行为吗?为什么我在设备轮换导致重新创建后获得Android的默认错误图标,即使我明确设置了自定义错误图标?
修改
我已经尝试在我的validateUsername()
方法中实现Drawable,但它没有用。
编辑2:
我想使用自定义错误图标,以便它与我的UI更好地融合,还因为我正在使用另一个自定义图标(绿色图标)显示为EditText
s'右{{1当他们的输入有效并且我希望他们彼此一致时。
现在我已经辞职了,我让Android使用默认的错误图标(即我没有在Drawable
方法中指定任何Drawable
)。当输入有效时,我将EditText的右侧Drawable设置为我自定义的“输入有效”图标,为了保持一致,我将其修改为与Android的indicator_input_error.png相同的大小。
尽管如此,我不喜欢这种方法(例如在未来的版本中,indicator_input_error.png图标可能会有所不同),我无法理解为什么在setError()
重新启动时我会继续获取默认图标-created。奇怪的是,第一次重新创建Fragment
时,如果EditText验证失败并且使用非空消息调用validateUsername(),我会获得自定义图标。在第二次(依此类推)重新创建Fragment
时,我获得了Android的默认图标。如果我输入了一些无效的文字,我会再次获得自定义图标,这很奇怪。
答案 0 :(得分:4)
真麻烦!我遇到了同样的问题。除了内置的错误图标外,我还有一个自定义图标来表示警告,并根据条件显示相应的图标。
当您进入时,在您的活动中调用onSave / onRestoreInstanceState()时,setError()会运行(即:旋转屏幕时)。
事实证明,大多数(所有?)股票Android小工具都会创建自己的可分配状态,以便在轮换期间保留其弹珠。这意味着许多简单的布局不需要实现他们自己的parcelable / serializable对象,就像你最有可能经历的那样。
如果深入查看TextView类,您将在onRestoreInstanceState()实现的末尾看到以下内容:
if (ss.error != null) {
final CharSequence error = ss.error;
// Display the error later, after the first layout pass
post(new Runnable() {
public void run() {
setError(error);
}
});
如您所见,仅检查ss.error(在TextView的onSaveInstanceState()期间保存)以查看它是否为空。如果是这样,它将通过调用setError(错误)进行恢复。简而言之,您的自定义图标在保存期间不会被分区,因此窗口小部件不会还原它 - 导致显示标准红色错误图标。鉴于TextView代码的年龄,我怀疑这是Google的疏忽。
你可以尝试重置你自己重写的onRestoreInstanceState()中的错误文本和图标,但由于小部件正在排队其setError()调用(通过调用post()),您的直接呼叫将超过它,导致您的图标显示一瞬间,只有在队列处理发生后才会被覆盖。
我通过在视图的队列中放置我自己的setError()来解决这个问题(也使用post())。这可能在学术上不合适并且干扰同步(因为我依赖于消息队列处理的顺序),但它解决了这个问题。
简而言之,在onRestoreInstanceState()中执行类似的操作:
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
// Call super first, to ensure that all the widget updates get in the queue first...
super.onRestoreInstanceState(savedInstanceState);
View view = getWindow().getDecorView().getRootView();
view.post(new Runnable()
{
public void run()
{
myEditText.setError(...);
.
.
.
}
});
}
这要消化很多。希望这有帮助!