如何使用InputFilter限制Android中EditText中的字符?

时间:2010-07-28 00:49:34

标签: android android-edittext

我想将字符限制为0-9,a-z,A-Z和空格键。设置inputtype我可以限制为数字,但我无法弄清楚Inputfilter查看文档的方式。

21 个答案:

答案 0 :(得分:177)

我在另一个论坛上发现了这个。像冠军一样工作。

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 });

答案 1 :(得分:129)

在Android版本中,InputFilters有点复杂,可以显示字典建议。有时你会得到一个SpannableStringBuilder,有时候是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();
        }
    }
}

答案 2 :(得分:102)

更容易:

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

答案 3 :(得分:60)

所有发布的答案都没有对我有用。我带来了自己的解决方案:

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 });

答案 4 :(得分:22)

将它的工作100%用于您的需要并且非常简单。

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

在strings.xml中

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

答案 5 :(得分:15)

避免输入类型中的特殊字符

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 });

答案 6 :(得分:7)

除了接受的答案之外,还可以使用例如android:inputType="textCapCharacters"作为<EditText>的属性,以便只接受大写字符(和数字)。

答案 7 :(得分:5)

由于某种原因,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;
    }
}

这并没有真正记录,但它是核心库和source is straightforward的一部分。我已经使用它一段时间了,到目前为止没有任何问题,但我承认我没有尝试做任何涉及spannables的复杂事件。

答案 8 :(得分:5)

这是正确的,最好的方法是使用以下方法在XML布局中修复它:

<EditText
android:inputType="text"
android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />
正如FlorianFröhlich正确指出的那样,它甚至适用于文本视图。

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

请注意,android:digits中提到的字符只会显示,所以请注意不要错过任何一组字符:)

答案 9 :(得分:4)

当我需要阻止用户将空字符串输入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});

}

答案 10 :(得分:2)

为了简化起见,我已经做了类似的事情:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{


    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapBlazorHub();
        endpoints.Select().Filter().OrderBy().Count().MaxTop(20);
        endpoints.MapODataRoute("api", "api", GetEdmModel());
        endpoints.MapFallbackToPage("/_Host");
    });
}

IEdmModel GetEdmModel()
{
    var odataBuilder = new ODataConventionModelBuilder();
    odataBuilder.EntitySet<DatabaseClaim>("DatabaseClaims");
    odataBuilder.EntitySet<EmployeeClaim>("EmployeeClaims");
    odataBuilder.EntitySet<Employee>("Employees");
    odataBuilder.EntitySet<Department>("Departments");

    var model = odataBuilder.GetEdmModel();

    //Add alternate key: find entity type, find property, add alternate key def
    IEdmEntityType employeeType = model.FindDeclaredEntitySet("Employees").EntityType();
    var userid = employeeType.FindProperty("UserId");
    ((EdmModel)model).AddAlternateKeyAnnotation(employeeType, new Dictionary<string, IEdmProperty> {
        {
            "UserId", userid
        }
    });

    return model;
}

通过这种方式,我们将源字符串的新部分中所有不需要的字符替换为空字符串。

[EnableQuery] [ODataRoute("{id}")] public async Task<IActionResult> Get(Guid id) { if (!ModelState.IsValid) { return BadRequest(ModelState); }; var record = await Context.Employees.FindAsync(id); if (record == null) { return NotFound(); } return Ok(record); } [EnableQuery] [ODataRoute("Employees(UserId={userid})")] public async Task<IActionResult> GetByUserId([FromODataUri] string userid) { if (!ModelState.IsValid) { return BadRequest(ModelState); }; var record = await Context.Employees .FirstOrDefaultAsync(r => r.UserId == userid); if (record == null) { return NotFound(); } return Ok(record); } 变量是我们所指的edit_text.filters = arrayOf(object : InputFilter { override fun filter( source: CharSequence?, start: Int, end: Int, dest: Spanned?, dstart: Int, dend: Int ): CharSequence? { return source?.subSequence(start, end) ?.replace(Regex("[^A-Za-z0-9 ]"), "") } }) 对象。

代码用edit_text编写。

答案 11 :(得分:1)

如果你是InputFilter的子类,你可以创建自己的InputFilter来过滤掉任何非字母数字字符。

InputFilter接口有一个方法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)

答案 12 :(得分:1)

忽略其他人处理过的内容,为了正确处理字典建议,我发现以下代码有效。

随着建议的增长,源代码会增长,因此我们必须查看在返回任何内容之前实际期望我们替换的字符数。

如果我们没有任何无效字符,请返回null以便进行默认替换。

否则我们需要从子串中提取出有效的字符,这些字符实际上将被放入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;
    } 
}; 

答案 13 :(得分:1)

防止edittext中的单词。 创建一个你可以随时使用的类。

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;
    }
}

答案 14 :(得分:1)

这是一个旧线程,但目的解决方案都存在问题(取决于设备/ Android版本/键盘)。

不同的方法

所以最终我采用了不同的方法,而不是使用InputFilter有问题的实现,我使用的是TextWatcherTextChangedListener的{​​{1}}。

完整代码(示例)

EditText

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 } }); 在Android中不是一个好的解决方案,因为它取决于键盘的实现。在将输入传递给InputFilter之前,将过滤键盘输入。但是,因为某些键盘具有EditText调用的不同实现,所以这是有问题的。

另一方面,InputFilter.filter()并不关心键盘实现,它允许我们创建一个简单的解决方案,并确保它可以在所有设备上运行。

答案 15 :(得分:0)

您可以在正则表达式中指定所需的字符,然后在InputFilter中使用它:

val regex = Regex("[a-zA-Z\\d ]")
    
editText.filters = arrayOf(InputFilter { source, _, _, _, _, _ ->
    source.filter { regex.matches(it.toString()) }
})

注意,我没有使用\w字符类,因为它包含下划线_

答案 16 :(得分:0)

我在科特林有相同的答案:

/**
 * Returns the filter of the editText'es CharSequence value when [filterType] is:
 * 1 -> letters; 2 -> letters and digits; 3 -> digits;
 * 4 -> digits and dots
 */
class InputFilterAlphanumeric(private val filterType: Int): InputFilter {
    override fun filter(source: CharSequence?, start: Int, end: Int, dest: Spanned?, dstart: Int, dend: Int): CharSequence {
        (source as? SpannableStringBuilder)?.let {sourceAsSpannableBuilder  ->
            for (i in (end - 1) downTo start) {
                val currentChar = source[i]
                when(filterType) {
                    1 -> {
                        if (!currentChar.isLetter() && !currentChar.isWhitespace()) {
                            sourceAsSpannableBuilder.delete(i, i + 1)
                        }
                    }
                    2 -> {
                        if (!currentChar.isLetterOrDigit() && !currentChar.isWhitespace()) {
                            sourceAsSpannableBuilder.delete(i, i + 1)
                        }
                    }
                    3 -> {
                        if (!currentChar.isDigit()) {
                            sourceAsSpannableBuilder.delete(i, i + 1)
                        }
                    }
                    4 -> {
                        if (!currentChar.isDigit() || !currentChar.toString().contains(".")) {
                            sourceAsSpannableBuilder.delete(i, i + 1)
                        }
                    }
                }
            }
            return source
        } ?: run {
            val filteredStringBuilder = StringBuilder()
            for (i in start until end) {
                val currentChar = source?.get(i)
                when(filterType) {
                    1 -> {
                        if (currentChar?.isLetter()!! || currentChar.isWhitespace()) {
                            filteredStringBuilder.append(currentChar)
                        }
                    }
                    2 -> {
                        if (currentChar?.isLetterOrDigit()!! || currentChar.isWhitespace()) {
                            filteredStringBuilder.append(currentChar)
                        }
                    }
                    3 -> {
                        if (currentChar?.isDigit()!!) {
                            filteredStringBuilder.append(currentChar)
                        }
                    }
                    4 -> {
                        if (currentChar?.isDigit()!! || currentChar.toString().contains(".")) {
                            filteredStringBuilder.append(currentChar)
                        }
                    }
                }
            }
            return filteredStringBuilder
        }
    }
}

并使用扩展功能获取该类:

fun EditText.filterByDataType(filterType: Int) {
    this.filters = arrayOf<InputFilter>(InputFilterAlphanumeric(filterType))
}

答案 17 :(得分:0)

首先添加到strings.xml

<string name="vin_code_mask">0123456789abcdefghjklmnprstuvwxyz</string>

XML

android:digits="@string/vin_code_mask"

Code在科特林:

edit_text.filters += InputFilter { source, start, end, _, _, _ ->
    val mask = getString(R.string.vin_code_mask)
    for (i in start until end) {
        if (!mask.contains(source[i])) {
            return@InputFilter ""
        }
    }
    null
}

奇怪,但是在模拟器的软键盘上却无法正常工作。

警告!以下代码将过滤除软件键盘的数字以外的所有字母和其他符号。智能手机上只会出现数字键盘。

edit_text.keyListener = DigitsKeyListener.getInstance(context.getString(R.string.vin_code_mask))

我通常还会设置maxLengthfiltersinputType

答案 18 :(得分:0)

这是我为“编辑文本”中的“名称”字段创建过滤器的方式。(第一个字母为CAPS,每个单词后仅允许一个空格。

public void setNameFilter() {
    InputFilter filter = new InputFilter() {
        @RequiresApi(api = Build.VERSION_CODES.KITKAT)
        public CharSequence filter(CharSequence source, int start, int end,
                                   Spanned dest, int dstart, int dend) {
            for (int i = start; i < end; i++) {
                if (dend == 0) {
                    if (Character.isSpaceChar(source.charAt(i)) ||
                            !Character.isAlphabetic(source.charAt(i))) {
                        return Constants.Delimiter.BLANK;
                    } else {
                        return String.valueOf(source.charAt(i)).toUpperCase();
                    }
                } else if (Character.isSpaceChar(source.charAt(i)) &&
                        String.valueOf(dest).endsWith(Constants.Delimiter.ONE_SPACE)) {
                    return Constants.Delimiter.BLANK;
                } else if ((!Character.isSpaceChar(source.charAt(i)) &&
                        !Character.isAlphabetic(source.charAt(i)))) {
                    return Constants.Delimiter.BLANK;
                }
            }
            return null;
        }
    };
    editText.setFilters(new InputFilter[]{filter, new InputFilter.LengthFilter(Constants.Length.NAME_LENGTH)});
}

答案 19 :(得分:0)

如果你想在你的输入中包含空格,那么在android:digit代码中添加空格,如上所示。

即使在Android 4.0以上的版本中,它也适用于我。

享受:)

答案 20 :(得分:0)

可以使用setOnKeyListener。在此方法中,我们可以自定义输入edittext