TextView.setError(CharSequence的错误)缺少图标 - 与运行果冻豆/ 4

2019-08-03 16:12发布

一些,但不是全部,运行果冻豆(4.2.1)设备似乎缺少应该出现在一个感叹号错误图标TextView (或者,更常见的是,一个EditText ),其具有通过在其上设置错误TextView.setError(CharSequence error)

在Galaxy Nexus的肯定似乎缺少图标。

其效果是,通过设置错误状态setError是当唯一明显EditText具有焦点。 这使得setError(...)因为它经常被用来鼓励用户返回到有用得多EditText来解决问题。 例如,你有一个用户名和密码表单条目的标准登录屏幕,当用户点击提交按钮被验证。 验证错误消息的用户名表格上设置不会显示出来,除非用户点击回到那个形式 - 这是什么错误图标旨在鼓励他们这样做!

测试:(有可能是一个更容易获得的EditText,但是这是一个非常广泛的使用)

  1. 打开设置
  2. 选择“添加帐户”(这是在“账户和同步”旧设备上)
  3. 选择“谷歌”作为帐户类型
  4. 选择“现有”(点击“下一步”后“登录”旧设备上)
  5. 离开“电子邮件” EditText空白,单击“密码” EditText

在这一点上,错误设定在“电子邮件” EditText说,它不能为空。 在不存在这个问题的设备,通常的错误图标显示,其扩展到当完整的错误消息EditText具有焦点。 银河Nexuses运行果冻豆,没有图标显示和错误是唯一可见的在所有的时候,“电子邮件” EditText有再次集中,并且仍然在这一点上缺少的图标。

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

使用setError(CharSequence error, Drawable icon)可能会解决的事情,但它会是不错的能够使用在不同的Android版本的股票错误图形。

Answer 1:

治标不治本! EditTextErrorFixed.java

虽然这确实是一个SDK的错误,我已经成功地使用反射的方法来获得按预期工作的图标。 我检查了它的工作原理与两个4.2和4.2.1,并验证了它的作品在我更新的Galaxy Nexus。

来源可以发现在这里。

该截图显示,在底部的图标EditTextErrorFixed即使聚焦变化仍然存在。 此外,它采用了另一种修正,其中如果用户按下一个已经空删除EditText错误消失(另一个bug?)。

为了方便起见,这里是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
        }
    }
}


Answer 2:

我知道有已经在这里解决。 它只是我尽量避免反射在Android上的一切费用。 如果确定与反射出去,但尝试下面首先我的解决方案,因为它可能会解决问题,而不必继承和体现。

Drawable d= getResources().getDrawable(R.drawable.ic_launcher);
            d.setBounds(0, 0, 
                    d.getIntrinsicWidth(), d.getIntrinsicHeight());

            et.setError("my error",d);


文章来源: Android OS bug with some devices running Jelly Bean/4.2.1 - TextView.setError(CharSequence error) Missing icon