35

すべてではありませんが、Jelly Bean (4.2.1) を実行している一部のデバイスでは、 経由でエラーが設定されているTextView(または、より一般的には)に表示される感嘆符のエラー アイコンが表示されていないようです。 EditTextTextView.setError(CharSequence error)

ここに画像の説明を入力 ここに画像の説明を入力

Galaxy Nexus には間違いなくアイコンがないようです。

その結果、 によって設定されたエラー ステータスは、にフォーカスがsetErrorある場合にのみ明らかになります。EditTextこれは、ユーザーが問題を解決するsetError(...)ためにそこに戻るように促すためによく使用されるため、あまり役に立ちません。EditTextたとえば、ユーザーが送信ボタンをクリックしたときに検証されるユーザー名とパスワードのフォーム エントリを含む標準のログイン画面があるとします。ユーザー名フォームに設定された検証エラー メッセージは、ユーザーがクリックしてそのフォームに戻らない限り表示されません。これは、ユーザーに実行を促すようにエラー アイコンが設計されているためです。

テストするには: (より簡単にアクセスできる EditText があるかもしれませんが、これは非常に広く利用されています)

  1. 設定を開く
  2. [アカウントを追加] を選択します (これは、古いデバイスの [アカウントと同期] にあります)。
  3. アカウントの種類として「Google」を選択します
  4. [既存] を選択します (古いデバイスでは [次へ] と [サインイン] をクリックした後)。
  5. 「メール」はEditText空欄のまま、「パスワード」をクリックEditText

この時点で、「電子メール」に、EditText空白にすることはできないというエラーが設定されます。この問題が発生していないデバイスでは、通常のエラー アイコンが表示されます。このアイコンは、EditTextフォーカスがあるときに完全なエラー メッセージに展開されます。Jelly Bean を実行している Galaxy Nexus では、アイコンは表示されず、「メール」EditTextに再びフォーカスが置かれたときにのみエラーが表示され、その時点ではまだアイコンが表示されません。

これはバグのように見えますが、他の人がそれを再現できるかどうか、問題が何であるかについてのアイデアがあるかどうか、および適切な回避策があるかどうかを確認したかったのです。

を使用setError(CharSequence error, Drawable icon)すると問題が解決する可能性がありますが、さまざまな Android バージョンでストック エラー グラフィックを使用できると便利です。

4

2 に答える 2

18

一時的な解決策!EditTextErrorFixed.java

これは確かにSDKのバグですが、リフレクションメソッドを使用してアイコンを意図したとおりに機能させることができました。4.2と4.2.1の両方で動作することを確認し、更新されたGalaxyNexusで動作することを確認しました。

ソースはここにあります。

EditTextErrorFixedスクリーンショットは、フォーカスが変更されても下部のアイコンが持続することを示しています。さらに、ユーザーがすでに空の状態でDeleteキーを押すとEditText、エラーが消えるという別の修正が組み込まれています(別のバグ?)。

デモ画像

便宜上、ここに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
        }
    }
}
于 2013-01-05T19:42:22.050 に答える
0

私はすでにここに解決策があることを知っています。Androidでのリフレクションを絶対に避けようとしているだけです。リフレクションに問題がない場合は、サブクラス化してリフレクトしなくても問題が解決する可能性があるため、最初に以下のソリューションを試してください。

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

            et.setError("my error",d);
于 2016-03-26T17:30:08.797 に答える