IT story

Android에서 EditText의 문자를 제한하기 위해 InputFilter를 어떻게 사용합니까?

hot-time 2020. 5. 27. 07:39
반응형

Android에서 EditText의 문자를 제한하기 위해 InputFilter를 어떻게 사용합니까?


문자를 0-9, az, AZ 및 스페이스 바로 제한하고 싶습니다. 입력 유형을 설정하면 숫자로 제한 할 수 있지만 입력 필터가 문서를 살펴 보는 방법을 알 수 없습니다.


나는 다른 포럼에서 이것을 발견했다. 챔피언처럼 작동합니다.

InputFilter filter = new InputFilter() {
    public CharSequence filter(CharSequence source, int start, int end,
            Spanned dest, int dstart, int dend) {
        for (int i = start; i < end; i++) {
            if (!Character.isLetterOrDigit(source.charAt(i))) {
                return "";
            }
        }
        return null;
    }
};
edit.setFilters(new InputFilter[] { filter });

InputFilter사전 제안을 표시하는 Android 버전에서는 약간 복잡합니다. 때로는 매개 변수 SpannableStringBuilder, 때로는 일반 String이 표시 source됩니다.

다음 InputFilter이 작동합니다. 이 코드를 자유롭게 개선하십시오!

new InputFilter() {
    @Override
    public CharSequence filter(CharSequence source, int start, int end,
            Spanned dest, int dstart, int dend) {

        if (source instanceof SpannableStringBuilder) {
            SpannableStringBuilder sourceAsSpannableBuilder = (SpannableStringBuilder)source;
            for (int i = end - 1; i >= start; i--) { 
                char currentChar = source.charAt(i);
                 if (!Character.isLetterOrDigit(currentChar) && !Character.isSpaceChar(currentChar)) {    
                     sourceAsSpannableBuilder.delete(i, i+1);
                 }     
            }
            return source;
        } else {
            StringBuilder filteredStringBuilder = new StringBuilder();
            for (int i = start; i < end; i++) { 
                char currentChar = source.charAt(i);
                if (Character.isLetterOrDigit(currentChar) || Character.isSpaceChar(currentChar)) {    
                    filteredStringBuilder.append(currentChar);
                }     
            }
            return filteredStringBuilder.toString();
        }
    }
}

훨씬 쉽게:

<EditText
    android:inputType="text"
    android:digits="0,1,2,3,4,5,6,7,8,9,*,qwertzuiopasdfghjklyxcvbnm" />

게시 된 답변 중 어느 것도 나를 위해 일하지 않았습니다. 나는 내 자신의 해결책을 찾았다.

InputFilter filter = new InputFilter() {
    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        boolean keepOriginal = true;
        StringBuilder sb = new StringBuilder(end - start);
        for (int i = start; i < end; i++) {
            char c = source.charAt(i);
            if (isCharAllowed(c)) // put your condition here
                sb.append(c);
            else
                keepOriginal = false;
        }
        if (keepOriginal)
            return null;
        else {
            if (source instanceof Spanned) {
                SpannableString sp = new SpannableString(sb);
                TextUtils.copySpansFrom((Spanned) source, start, sb.length(), null, sp, 0);
                return sp;
            } else {
                return sb;
            }           
        }
    }

    private boolean isCharAllowed(char c) {
        return Character.isLetterOrDigit(c) || Character.isSpaceChar(c);
    }
}
editText.setFilters(new InputFilter[] { filter });

이 작업을 100 % 필요하고 매우 간단하게 사용하십시오.

<EditText
android:inputType="textFilter"
android:digits="@string/myAlphaNumeric" />

strings.xml에서

<string name="myAlphaNumeric">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</string>

입력 유형에서 특수 문자를 피하려면

public static InputFilter filter = new InputFilter() {
    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        String blockCharacterSet = "~#^|$%*!@/()-'\":;,?{}=!$^';,?×÷<>{}€£¥₩%~`¤♡♥_|《》¡¿°•○●□■◇◆♧♣▲▼▶◀↑↓←→☆★▪:-);-):-D:-(:'(:O 1234567890";
        if (source != null && blockCharacterSet.contains(("" + source))) {
            return "";
        }
        return null;
    }
};

아래와 같이 필터를 편집 텍스트로 설정할 수 있습니다

edtText.setFilters(new InputFilter[] { filter });

허용되는 답변 외에도 대문자 (및 숫자) 만 허용하기 위해 예를 들어 android:inputType="textCapCharacters"속성을 속성으로 사용할 수도 있습니다 <EditText>.


어떤 이유로 android.text.LoginFilter 클래스의 생성자는 패키지 범위이므로 직접 확장 할 수는 없습니다 (이 코드와 동일하더라도). 그러나 LoginFilter.UsernameFilterGeneric을 확장 할 수 있습니다! 그런 다음이 있습니다.

class ABCFilter extends LoginFilter.UsernameFilterGeneric {
    public UsernameFilter() {
        super(false); // false prevents not-allowed characters from being appended
    }

    @Override
    public boolean isAllowed(char c) {
        if ('A' <= c && c <= 'C')
            return true;
        if ('a' <= c && c <= 'c')
            return true;

        return false;
    }
}

이것은 실제로 문서화되어 있지는 않지만 핵심 lib의 일부이며 소스는 간단 합니다. 나는 지금까지 그것을 사용해 왔지만 지금까지 아무런 문제가 없었지만 스패너 블과 관련된 복잡한 작업은 시도하지 않았다는 것을 인정합니다.


XML 레이아웃 자체에서 다음을 사용하여 수정하는 가장 좋은 방법은 다음과 같습니다.

<EditText
android:inputType="text"
android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />

Florian Fröhlich가 올바르게 지적했듯이 텍스트보기에도 잘 작동합니다.

<TextView
android:inputType="text"
android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />

주의 단어,에 언급 된 문자 android:digits만 표시되므로 문자 집합을 놓치지 않도록주의하십시오. :)


이 간단한 솔루션은 사용자가 EditText에 빈 문자열을 입력하지 못하게해야 할 때 효과적이었습니다. 물론 더 많은 문자를 추가 할 수 있습니다.

InputFilter textFilter = new InputFilter() {

@Override

public CharSequence filter(CharSequence c, int arg1, int arg2,

    Spanned arg3, int arg4, int arg5) {

    StringBuilder sbText = new StringBuilder(c);

    String text = sbText.toString();

    if (text.contains(" ")) {    
        return "";   
    }    
    return c;   
    }   
};

private void setTextFilter(EditText editText) {

    editText.setFilters(new InputFilter[]{textFilter});

}

InputFilter를 서브 클래 싱하는 경우 영숫자가 아닌 문자를 필터링하는 고유 한 InputFilter를 작성할 수 있습니다.

InputFilter Interface에는 한 가지 메소드가 있으며 filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend), EditText에 입력 된 문자에 대해 알아야하는 모든 정보를 제공합니다.

고유 한 InputFilter를 작성하면 setFilters (...)를 호출하여 EditText에 지정할 수 있습니다.

http://developer.android.com/reference/android/text/InputFilter.html#filter(java.lang.CharSequence, int, int, android.text.Spanned, int, int)


Ignoring the span stuff that other people have dealt with, to properly handle dictionary suggestions I found the following code works.

The source grows as the suggestion grows so we have to look at how many characters it's actually expecting us to replace before we return anything.

If we don't have any invalid characters, return null so that the default replacement occurs.

Otherwise we need to extract out the valid characters from the substring that's ACTUALLY going to be placed into the EditText.

InputFilter filter = new InputFilter() { 
    public CharSequence filter(CharSequence source, int start, int end, 
    Spanned dest, int dstart, int dend) { 

        boolean includesInvalidCharacter = false;
        StringBuilder stringBuilder = new StringBuilder();

        int destLength = dend - dstart + 1;
        int adjustStart = source.length() - destLength;
        for(int i=start ; i<end ; i++) {
            char sourceChar = source.charAt(i);
            if(Character.isLetterOrDigit(sourceChar)) {
                if(i >= adjustStart)
                     stringBuilder.append(sourceChar);
            } else
                includesInvalidCharacter = true;
        }
        return includesInvalidCharacter ? stringBuilder : null;
    } 
}; 

to prevent words in edittext. create a class that u could use anytime.

public class Wordfilter implements InputFilter
{
    @Override
    public CharSequence filter(CharSequence source, int start, int end,Spanned dest, int dstart, int dend) {
        // TODO Auto-generated method stub
        boolean append = false;
        String text = source.toString().substring(start, end);
        StringBuilder str = new StringBuilder(dest.toString());
        if(dstart == str.length())
        {
            append = true;
            str.append(text);
        }
        else
            str.replace(dstart, dend, text);
        if(str.toString().contains("aaaaaaaaaaaa/*the word here*/aaaaaaaa"))
        {
            if(append==true)
                return "";
            else
                return dest.subSequence(dstart, dend);
        }
        return null;
    }
}

This is an old thread, but the purposed solutions all have issues (depending on device / Android version / Keyboard).

DIFFERENT APPROACH

So eventually I went with a different approach, instead of using the InputFilter problematic implementation, I am using TextWatcher and the TextChangedListener of the EditText.

FULL CODE (EXAMPLE)

editText.addTextChangedListener(new TextWatcher() {

    @Override
    public void afterTextChanged(Editable editable) {
        super.afterTextChanged(editable);

        String originalText = editable.toString();
        int originalTextLength = originalText.length();
        int currentSelection = editText.getSelectionStart();

        // Create the filtered text
        StringBuilder sb = new StringBuilder();
        boolean hasChanged = false;
        for (int i = 0; i < originalTextLength; i++) {
            char currentChar = originalText.charAt(i);
            if (isAllowed(currentChar)) {
                sb.append(currentChar);
            } else {
                hasChanged = true;
                if (currentSelection >= i) {
                    currentSelection--;
                }
            }
        }

        // If we filtered something, update the text and the cursor location
        if (hasChanged) {
            String newText = sb.toString();
            editText.setText(newText);
            editText.setSelection(currentSelection);
        }
    }

    private boolean isAllowed(char c) {
        // TODO: Add the filter logic here
        return Character.isLetter(c) || Character.isSpaceChar(c);
    }
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        // Do Nothing
    }

    @Override
    onTextChanged(CharSequence s, int start, int before, int count) {
        // Do Nothing
    }
});

The reason InputFilter is not a good solution in Android is since it depends on the keyboard implementation. The Keyboard input is being filtered before the input is passed to the EditText. But, because some keyboards have different implementations for the InputFilter.filter() invocation, this is problematic.

On the other hand TextWatcher does not care about the keyboard implementation, it allows us to create a simple solution and be sure it will work on all devices.


It is possible to use setOnKeyListener. In this method, we can customize the input edittext !


if you want to include the white space in your input as well then add space in android:digit code as shown above.

It works fine for me even in version above android 4.0.

enjoy :)

참고URL : https://stackoverflow.com/questions/3349121/how-do-i-use-inputfilter-to-limit-characters-in-an-edittext-in-android

반응형