【问题标题】:How to use regular expression in Android如何在 Android 中使用正则表达式
【发布时间】:2012-05-06 20:38:23
【问题描述】:

我有一个 numberDecimal EditText,我想使用正则表达式对其进行验证。在验证中我想要的是:

  1. 在小数点前,我要输入的最大数字是三位,并且数字不应像2,23,342等以零开头。

  2. 小数点后我想输入的最大位数是.1.3.6等。

所以我允许用户输入的数字是2.132.5444.8564.9等。

但在我的代码中,发生的情况是:

  1. 它允许用户在小数点前输入多于三位的数字,例如345644445555,之后不允许我输入小数点.

  2. 它允许我在小数点前输入0作为数字的开头。

那么为什么会发生这种情况,我使用的正则表达式有什么问题吗?如果有人知道,请帮我解决这个问题。

我使用过的代码:

weightEditText.addTextChangedListener(new TextWatcher() 
{           
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {               
    }           
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {            
    }           
    @Override
    public void afterTextChanged(Editable s) 
    {
        Pattern mPattern = Pattern.compile("^([1-9][0-9]{0,2})?(\\.[0-9]?)?$");

        Matcher matcher = mPattern.matcher(s.toString());               
        if(!matcher.find())
        {
            weightEditText.setText(); // Don't know what to place                   
        }
    }
});

【问题讨论】:

标签: android regex android-edittext


【解决方案1】:

InputFilter 中单独检查dest 没有任何意义;这就是该领域已经存在的。将正则表达式匹配更改为针对source,如果您只想检查某些字符是否被接受到该字段中,这将是合适的。但是,您要检查字段格式,而不仅仅是逐个字符过滤输入。这要复杂得多。

每次用户对tempEditText 的内容进行更改时,系统都会调用过滤器的filter 方法实际进行更改之前。它传递当前字段内容和建议的更改(可以是插入/追加、删除或替换)。更改由源 CharSequence source(要添加到字段的字符(如果有))、源内的范围开始和结束索引(范围不一定是 source 的全部)、Spanned dest 表示(更改前的当前字段内容)和范围 dstart 和 dest 内的 dend 索引,建议替换为指示的 source 范围。

filter 的工作是修改更改(如有必要)并返回 CharSequence 以使用(全部)代替source(或null 继续使用source )。而不是像现在这样检查dest,您需要检查更改是否会导致可接受的字段。为此,您将需要更复杂的逻辑。 (请特别注意,新字符可能用于插入末尾以外的位置;另外,当用户删除和添加字符时,将调用filter。)

实现TextWatcher 可能更容易。在它的beforeTextChanged 方法中,您可以记录当前内容,在它的afterTextChanged 方法中,您可以检查(使用正则表达式)内容是否可以接受,如果不可以,则恢复更改前的内容。 (但请确保更改之前的文本是可接受的。如果不是,请替换一些可接受的内容 - 例如清除字段。否则您的代码将进入无限循环,因为将再次调用 TextWatcher当您更正字段内容时。)

您的正则表达式也有错误:它允许前导零。这是修复此问题的改进版本(并删除了一组不必要的括号):

"^([1-9][0-9]{0,2})?(\\.[0-9]?)?$"

(顺便说一句:您可以使用\\d 而不是[0-9]。)

编辑

这是我对您的编辑的编辑:

weightEditText.addTextChangedListener(new TextWatcher() 
{           
    private static final Pattern sPattern
        = Pattern.compile("^([1-9][0-9]{0,2})?(\\.[0-9]?)?$");

    private CharSequence mText;

    private boolean isValid(CharSequence s) {
        return sPattern.matcher(s).matches();
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count){
    }           

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count,
            int after){
        mText = isValid(s) ? new CharSequence(s) : "";
    }           

    @Override
    public void afterTextChanged(Editable s) 
    {
        if (!isValid(s))
        {
            weightEditText.setText(mText);
        }
        mText = null;
    }
});

【讨论】:

  • 我已经编辑了我的答案并使用 TextWatcher 来完成。但无法找到在 beforeTextChange 方法中写什么的线索。你能看看我编辑的答案,告诉我应该怎么做。
  • @Anshuman - 首先,将您的模式匹配移动到一个单独的方法(例如,称为isValid)。然后在 TextWatcher 中声明一个字段来存储更改前的文本:class MyTextWatcher { private CharSequence mText; ... public void beforeTextChanged (CharSequence s, int start, int count, int after) { mText = isValid(s) ? new CharSequence(s) : ""; }。最后,如果在afterTextChanged 中测试失败,请致电weightEditText.setText(mText);。此外,在退出 afterTextChanged 之前始终设置 mText = null;,因为该值现在无用。
  • @Anshuman - 我还将 mPattern 设为 static final 字段;编译不止一次是没有意义的。
  • 是的,它的工作原理......非常感谢......最后一个问题是可以改变我的模式,它也不允许输入小数点作为开始数字。
  • @Anshuman - 当然:"^([1-9][0-9]{0,2}(\\.[0-9]?)?)?$"。 (附言我用示例代码更新了我的答案。我很高兴你能正常工作。)
【解决方案2】:

也许我的实现会帮助任何人:

    etRepeaterCallsign.addTextChangedListener(new TextWatcher() {
        private final Pattern sPattern
                = Pattern.compile("^([A-Z]{0,2})?(\\d)?([A-Z-]{0,5})"); // ^([1-9][0-9]{0,2})?(\\.[0-9]?)?$

        private CharSequence mText;

        private boolean isValid(CharSequence s) {
            return sPattern.matcher(s).matches();
        }

        @Override
        public void beforeTextChanged(CharSequence r, int start, int count,
                                      int after) {
            mText = r.toString();
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            bIsEdit = true;
        }
        @Override
        public void afterTextChanged(Editable s) {
            etRepeaterCallsign.removeTextChangedListener(this);

            int iCursorPosition = etRepeaterCallsign.getSelectionStart();
            etRepeaterCallsign.setText("");
            if (isValid(s))
                etRepeaterCallsign.append(s);
            else
                etRepeaterCallsign.append(mText);

            etRepeaterCallsign.setSelection(iCursorPosition);

            etRepeaterCallsign.addTextChangedListener(this);

        }
    });

【讨论】:

    【解决方案3】:

    您可以只解析数字并检查它是否

    【讨论】:

    • 你能举个例子给我解释一下吗..这对我有帮助
    【解决方案4】:

    我使用以下代码尝试了您的模式。它可以完美地用作 2.1、32.5、444.8、564.9 等。

    我的代码:

    public class WebPush extends Activity {  
        EditText editTxt;
        private TextView regresult;  
    
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main); 
    
            editTxt = (EditText) findViewById(R.id.editID);
            regresult = (TextView) findViewById(R.id.txtID);
    
            String urName = editTxt.getText().toString();
            editTxt.addTextChangedListener(new TextWatcher() {
    
                @Override
                public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
                }
    
                @Override
                public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,int arg3) {
                }       
    
                @Override
                public void afterTextChanged(Editable s) {
                    if (editTxt.getText().toString().matches("(^([0-9]{0,3})?)(\\.[0-9]{0,1})?$"))
                    {
                        regresult.setText("");
                    }
                    else
                    {
                        regresult.setText("invalid number");
                    }
                }
            });
        }
    }
    

    【讨论】:

    • 但我不想在单独的 TextView 中显示错误。相反,我不允许用户在 EditBox 中输入错误的数字。我的意思是说,如果输入的数字是正确的,那么只有它允许用户输入数字。如果它是错误的,那么它不允许用户输入。那你知道怎么做吗
    【解决方案5】:

    您可以尝试以下方式:^[1-9][0-9]{0,2}(\\.\\d)?$。这应该匹配任何不以 0 (^[1-9]) 开头且后跟最多两个数字 ([0-9]{0,2}) 的数字。正则表达式还允许使用可选的十进制值 ((\\.\\d)?$)。

    话虽如此,理想情况下,您应该将字符串值解析为doublefloat,并使用实际数值进行所需的验证。

    要将您的string 解析为double 值,您需要像这样使用Double.parseDouble(String s)double myValue = Double.parseDouble(EditText.getText());

    【讨论】:

    • 我使用了你的模式。现在它不允许我在 EditText 中输入任何内容,如果我使用单个 \ 它显示错误,还有一件事。如果您在我的示例代码中向我展示会更好,请建议我如何将字符串值解析为 double,因为它存储在 Spanned dest 变量中
    • @Anshuman:我已经改变了我的答案。在 Java 中,您需要转义 `,因此您需要成对使用它们,根据我所做的更改。我还提供了一个指向 JavaDoc 的链接,其中介绍了如何将 String 解析为 double。
    • 我在我的代码中使用了你的模式,比如 Pattern.compile("(^[1-9])([0-9]{0,2})((\\.\\ d)?$)");.现在发生的事情是它不允许我在 EditBox 中输入任何数字
    • 但是当我在简单的 java 项目中使用此代码并在控制台中运行时,它工作正常,并且当我输入错误的数字时显示错误。但是当我使用相同的代码并尝试检查 EditText 输入过滤器方法中的错误时,它不起作用为什么会发生这种情况。
    • @Anshuman:我自己尝试过,它适用于12.1123.2 等字符串值,但对于02.1 无效。
    猜你喜欢
    • 2011-11-13
    • 2020-09-14
    • 1970-01-01
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 2010-11-06
    • 1970-01-01
    相关资源
    最近更新 更多