web-dev-qa-db-ja.com

IndexOutOfBoundsException setSpan(0 ... 1)が長さ0を超えて終了します

私はこのライブラリをラベル付きのマテリアルeditTextに使用しています: https://github.com/rey5137/Material/wiki/Text-Field 素敵なライブラリ:)

だが...

次のコードを使用して、入力された記号が正しいことを確認しています。

private boolean hasCorrectSymbols(String input){
        String tre = "[A-Za-z0-9\\@\\#\\$\\%\\&\\*\\(\\)\\-\\+\\_\\;\\:\\?\\.\\,\\!]+$";
        if (input.matches(tre)){
            return true;
        }
        return false;
    }

textWatcherを使用している正しい記号をチェックするために:

mEditPass.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (s.length() == 1 && !loginPassHasCorrectSymbols(s.toString())){
                    mEditPass.getText().clear();
                    String mess = getString(R.string.toast_login_useLatin);
                    showToastMessage(mess);
                } else if (s.length() >1 && !loginPassHasCorrectSymbols(s.toString())) {
                    String mess = getString(R.string.toast_login_useLatin);
                    showToastMessage(mess);
                    String text = s.toString();
                    text = text.substring(0, start);
                    mEditPass.setText(text);
                    mEditPass.setSelection(start);
                }
            }

            @Override
            public void afterTextChanged(Editable s) {}
        });

たとえば、最初の記号が正しく、2番目の記号が間違っている場合、システムは最後に入力された(間違った)記号を切り取り、カーソルを最後のテキスト位置に設定しますが、最初の記号が禁止されている記号の場合、次のエラーでクラッシュします。

Java.lang.IndexOutOfBoundsException: setSpan (0 ... 1) ends beyond length 0
            at Android.text.SpannableStringBuilder.checkRange(SpannableStringBuilder.Java:1016)
            at Android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.Java:592)
            at Android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.Java:588)
            at Android.text.method.PasswordTransformationMethod.onTextChanged(PasswordTransformationMethod.Java:108)
            at Android.text.SpannableStringBuilder.sendTextChanged(SpannableStringBuilder.Java:962)
            at Android.text.SpannableStringBuilder.replace(SpannableStringBuilder.Java:496)
            at Android.text.SpannableStringBuilder.replace(SpannableStringBuilder.Java:435)
            at Android.text.SpannableStringBuilder.replace(SpannableStringBuilder.Java:30)
            at Android.view.inputmethod.BaseInputConnection.replaceText(BaseInputConnection.Java:683)
            at Android.view.inputmethod.BaseInputConnection.commitText(BaseInputConnection.Java:198)
            at com.Android.internal.widget.EditableInputConnection.commitText(EditableInputConnection.Java:183)
            at com.Android.internal.view.IInputConnectionWrapper.executeMessage(IInputConnectionWrapper.Java:279)
            at com.Android.internal.view.IInputConnectionWrapper$MyHandler.handleMessage(IInputConnectionWrapper.Java:77)
            at Android.os.Handler.dispatchMessage(Handler.Java:102)
            at Android.os.Looper.loop(Looper.Java:136)
            at Android.app.ActivityThread.main(ActivityThread.Java:5097)
            at Java.lang.reflect.Method.invokeNative(Native Method)
            at Java.lang.reflect.Method.invoke(Method.Java:515)
            at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:785)
            at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:601)
            at dalvik.system.NativeStart.main(Native Method) 

なぜそれが起こるのか考えはありますか?そして、これを修正する方法は??

6
Stan Malcolm

このコードスニペットでは、EditTextに表示されるテキストを短くしますが(最後の有効な位置はstart-1になります)、それでも選択位置をstartに設定しようとします。

                text = text.substring(0, start);
                mEditPass.setText(text);
                mEditPass.setSelection(start);

[編集済み]

Toastメッセージがユーザーにエラーの修正を促していると仮定すると、実際に実行したいのは、EditTextの最初の文字に不正な記号を設定することだと思います。これを行うためのサンプルコードは次のとおりです。

// A reusable Pattern (at the class level) that defines the regex for bad characters.
private static final Pattern ILLEGAL_CHAR_PATTERN = Pattern.compile(
    "[^A-Za-z0-9\\@\\#\\$\\%\\&\\*\\(\\)\\-\\+\\_\\;\\:\\?\\.\\,\\!]"
);

    // Replacement for your listener code.
    mEditPass.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            if (s.length() == 0 || count == 0) {
                return;
            }
            Matcher matcher = ILLEGAL_CHAR_PATTERN.matcher(s);
            if (matcher.find()) {
                int firstIllegalPos = matcher.start();
                mEditPass.setSelection(firstIllegalPos);
                String mess = getString(R.string.toast_login_useLatin);
                showToastMessage(mess);
            }
        }

        @Override
        public void afterTextChanged(Editable s) {
        }
    });
4
cybersam

エラーは、スパン可能なテキストを開始前に終了していることを示しています。終了するために指定した文字を探し、開始前に表示されます

1
blackHawk

この問題は、次のコードを追加することで修正されました。

mEditPass.getText().clearSpans();

mEditPass.getText().clear();
1
Stan Malcolm

文字列にスペースをもう1つ追加してから、

mEditPass.setSelection(new string);
0
Vikash Sharma