一些(但不是全部)运行 Jelly Bean (4.2.1) 的设备似乎缺少应该出现在 TextView
(或更常见的是 上的感叹号错误图标) EditText
) 通过 TextView.setError(CharSequence error)
设置了错误.
Galaxy Nexus 显然缺少图标。
效果是 setError
设置的错误状态只有在 EditText
有焦点时才明显。这使得 setError(...)
的用处大大降低,因为它通常用于鼓励用户返回该 EditText
以解决问题。例如,您有一个标准登录屏幕,其中包含用户单击提交按钮时验证的用户名和密码表单条目。除非用户单击返回该表单,否则不会显示在用户名表单上设置的验证错误消息——这是错误图标旨在鼓励他们这样做的!
测试:(可能有一个更容易访问的 EditText,但这个非常广泛)
- 打开设置
- 选择“添加帐户”(在旧设备的“帐户和同步”中)
- 选择“Google”作为帐户类型
- 选择“现有”(在旧设备上单击“下一步”和“登录”后)
- 将“电子邮件”
EditText
留空,点击“密码”EditText
此时,在“电子邮件”EditText
上设置了一个错误,说明它不能为空。在没有此问题的设备上,会显示通常的错误图标,当 EditText
具有焦点时,该图标会扩展为完整的错误消息。在运行 Jelly Bean 的 Galaxy Nexuses 上,不显示任何图标,并且该错误仅在“电子邮件”EditText
再次获得焦点且此时仍缺少图标时才可见。
这看起来像一个错误,但我想检查其他人是否可以重现它,了解问题可能是什么,并有一个好的解决方法。
使用 setError(CharSequence error, Drawable icon)
可能会解决问题,但如果能够在不同的 Android 版本中使用库存错误图形,那就太好了。
最佳答案
临时解决方案! EditTextErrorFixed.java
虽然这确实是一个 SDK 错误,但我已经设法使用反射方法让图标按预期工作。我检查了它是否适用于 4.2 和 4.2.1,并确认它适用于我更新的 Galaxy Nexus。
来源可以找到here.
截图显示底部EditTextErrorFixed
的图标在焦点改变时仍然存在。此外,它还包含另一个修复,如果用户在已经为空的 EditText
上按 Delete,错误就会消失(另一个错误?)。
为方便起见,这里是 EditTextErrorFixed
源码;该类可以很容易地在 XML 中使用:
package com.olegsv.showerrorfixeddemo;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.EditText;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* EditText which addresses issues with the error icon
* (http://stackoverflow.com/q/13756978/832776) and also the error icon
* disappearing on pressing delete in an empty EditText
*/
public class EditTextErrorFixed extends EditText {
public EditTextErrorFixed(Context context) {
super(context);
}
public EditTextErrorFixed(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EditTextErrorFixed(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* Don't send delete key so edit text doesn't capture it and close error
*/
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (TextUtils.isEmpty(getText().toString()) && keyCode == KeyEvent.KEYCODE_DEL)
return true;
else
return super.onKeyPreIme(keyCode, event);
}
/**
* Keep track of which icon we used last
*/
private Drawable lastErrorIcon = null;
/**
* Resolve an issue where the error icon is hidden under some cases in JB
* due to a bug http://code.google.com/p/android/issues/detail?id=40417
*/
@Override
public void setError(CharSequence error, Drawable icon) {
super.setError(error, icon);
lastErrorIcon = icon;
// if the error is not null, and we are in JB, force
// the error to show
if (error != null /* !isFocused() && */) {
showErrorIconHax(icon);
}
}
/**
* In onFocusChanged() we also have to reshow the error icon as the Editor
* hides it. Because Editor is a hidden class we need to cache the last used
* icon and use that
*/
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
showErrorIconHax(lastErrorIcon);
}
/**
* Use reflection to force the error icon to show. Dirty but resolves the
* issue in 4.2
*/
private void showErrorIconHax(Drawable icon) {
if (icon == null)
return;
// only for JB 4.2 and 4.2.1
if (android.os.Build.VERSION.SDK_INT != Build.VERSION_CODES.JELLY_BEAN &&
android.os.Build.VERSION.SDK_INT != Build.VERSION_CODES.JELLY_BEAN_MR1)
return;
try {
Class<?> textview = Class.forName("android.widget.TextView");
Field tEditor = textview.getDeclaredField("mEditor");
tEditor.setAccessible(true);
Class<?> editor = Class.forName("android.widget.Editor");
Method privateShowError = editor.getDeclaredMethod("setErrorIcon", Drawable.class);
privateShowError.setAccessible(true);
privateShowError.invoke(tEditor.get(this), icon);
} catch (Exception e) {
// e.printStackTrace(); // oh well, we tried
}
}
}
关于某些运行 Jelly Bean/4.2.1 的设备的 Android 操作系统错误 - TextView.setError(CharSequence error) 缺少图标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13756978/