运行Jelly Bean / 4.2.1的一些设备的Android操作系统错误 – TextView.setError(CharSequence错误)Missing icon

运行Jelly Bean(4.2.1)的一些设备(但不是全部)似乎缺less应该出现在TextView上的感叹号错误图标(或者更常见的是EditText ),该图标通过TextView.setError(CharSequence error)

在这里输入图像说明在这里输入图像说明

Galaxy Nexus绝对似乎缺less了这个图标。

效果是由setError设置的错误状态只有在EditText具有焦点时才会显现。 这使得setError(...)更加有用,因为它经常被用来鼓励用户返回EditText来解决问题。 例如,您有一个标准的login屏幕,其中包含用户名和密码表单条目,当用户单击提交button时,该条目将被validation。 在用户名表单上设置的validation错误消息将不会显示,除非用户单击回到该表单 – 这是错误图标旨在鼓励他们这样做!

testing:(可能有一个更容易访问的EditText,但这个是非常广泛的可用)

  1. 打开设置
  2. select“添加帐户”(这是在旧设备上的“帐户和同步”)
  3. select“Google”作为帐户types
  4. select“现有”(在旧设备上点击“下一步”和“login”后)
  5. 将“电子邮件” EditText留空,单击“密码” EditText

此时,在“电子邮件” EditText上设置了一个错误,表示它不能为空。 在没有此问题的设备上,会显示常见的错误图标,当EditText具有焦点时,会将其展开为完整的错误消息。 在运行Jelly Bean的Galaxy Nexus上,没有图标显示,只有当' EditText重新对焦时,错误才会显示,但仍然没有图标。

这看起来像一个错误,但我想检查其他人是否可以重现它,有什么问题的想法,并有一个很好的解决方法。

使用setError(CharSequence error, Drawable icon)可能会修复一些问题,但能够在不同的Android版本中使用股票错误graphics将会很好。

临时解决scheme! EditTextErrorFixed.java

虽然这确实是一个SDK错误,但我已经设法使用reflection方法使图标按预期工作。 我检查了它与4.2和4.2.1兼容,并validation它可以在我更新的Galaxy Nexus上运行。

来源可以在这里find。

屏幕截图显示即使焦点更改,底部的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 } } } 

我知道这里有一个解决scheme。 它只是我尽量避免反思在Android上不惜一切代价。 如果你确定反思去了,但先试试我的解决scheme,因为它可以解决问题,而不必子类和反映。

 Drawable d= getResources().getDrawable(R.drawable.ic_launcher); d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); et.setError("my error",d);