web-dev-qa-db-fra.com

Comment utiliser l'expression régulière dans Android

J'ai un numberDecimal EditText que je veux valider en utilisant une expression régulière. En validation ce que je veux c'est:

  1. Avant la virgule décimale, le chiffre maximum que je veux entrer est de trois et le chiffre ne doit pas commencer par zéro comme 2,23,342, etc.

  2. Après la virgule décimale, le chiffre maximum que je veux entrer est un chiffre tel que .1, .3, .6, etc.

Ainsi, le nombre que je permets à l'utilisateur d'entrer est comme 2.1, 32.5, 444.8, 564.9, etc.

Mais dans mon code, ce qui se passe est:

  1. Il permet à l'utilisateur de saisir plus d'un nombre à trois chiffres avant la virgule décimale, comme 3456, 4444, 5555, mais ne me permet pas d'entrer une décimale plus tard.

  2. Cela me permet d'entrer 0 avant le point décimal en tant que début du chiffre.

Alors, pourquoi cela se produit-il? Quelque chose ne va pas dans l'expression régulière que j'ai utilisée? Si quelqu'un le sait, aidez-moi s'il vous plaît à résoudre ce problème.

Code que j'ai utilisé:

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

Il n’est jamais inutile d’examiner dest seul dans une InputFilter; c'est ce qui est déjà présent sur le terrain. Modifiez la correspondance de l'expression régulière pour qu'elle corresponde à source et il serait approprié de vérifier uniquement que certains caractères ont été acceptés dans le champ. Cependant, vous souhaitez vérifier la mise en forme des champs et pas seulement filtrer les entrées, caractère par caractère. C'est beaucoup plus complexe.

Chaque fois que l'utilisateur modifie le contenu de tempEditText, le système appelle la méthode filter de votre filtre avant le changement est réellement effectué. Il transmet le contenu du champ actuel et la modification proposée (qui peut être insérer/ajouter, supprimer ou remplacer). La modification est représentée par un CharSequence source source (les caractères éventuels à ajouter au champ), des index de début et de fin de plage dans la source (la plage ne correspond pas nécessairement à source), un Spanned dest (le contenu du champ actuel avant le changement) et les plages dstart et dend dans dest qu'il est proposé de remplacer par la plage source indiquée.

Le travail de filter consiste à modifier le changement (si nécessaire) et à renvoyer un CharSequence à utiliser (dans son intégralité) à la place de source (ou null pour continuer et utiliser source). Plutôt que de vérifier dest comme vous le faites maintenant, vous devrez vérifier si le changement aboutira à un champ acceptable. Pour ce faire, vous aurez besoin d'une logique plus complexe. (Notez en particulier que les nouveaux caractères peuvent être destinés à être insérés ailleurs qu'à la fin; filter sera également appelé lorsque l'utilisateur supprimera ou ajoutera des caractères.)

Il peut être plus facile de mettre en œuvre une TextWatcher . Dans sa méthode beforeTextChanged, vous pouvez enregistrer le contenu actuel et dans sa méthode afterTextChanged, vous pouvez vérifier (à l'aide d'une expression régulière) si le contenu est acceptable et, si ce n'est pas le cas, restaurer le contenu avant modification. (Assurez-vous cependant que le texte avant la modification était acceptable. Dans le cas contraire, remplacez-le par un élément acceptable, tel que la suppression du champ. Dans le cas contraire, votre code entrera dans une boucle infinie, car la TextWatcher sera invoquée à nouveau corrigez le contenu du champ.)

Vous avez également une erreur dans votre expression régulière: elle autorise un zéro non significatif. Voici une version améliorée qui résout ce problème (et supprime un ensemble de parenthèses inutiles):

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

(En passant: vous pouvez utiliser \\d au lieu de [0-9].)

MODIFIER

Voici mon édition de votre édition:

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;
    }
});
23
Ted Hopp

Peut-être que ma mise en œuvre aidera n'importe qui: 

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

        }
    });
2
Serg Vorontsov

Vous pouvez simplement analyser le nombre et vérifier qu'il est <1000 et que 10 * nombre est un entier, tandis que num ne l'est pas. Ce serait probablement plus lisible aussi.

1
assylias

Vous pouvez essayer quelque chose comme ceci: ^[1-9][0-9]{0,2}(\\.\\d)?$. Cela doit correspondre à tout numéro qui ne commence pas par 0 (^[1-9]) et qui est suivi d’au plus deux chiffres ([0-9]{0,2}). L'expression régulière permet également une valeur décimale optionnelle ((\\.\\d)?$).

Cela étant dit, idéalement, vous devriez analyser la valeur de chaîne avec une variable double ou float et effectuer les validations nécessaires à l'aide de la valeur numérique réelle. 

Pour analyser votre string dans une valeur double, vous devrez utiliser le Double.parseDouble (String s) like so: double myValue = Double.parseDouble(EditText.getText());

0
npinti

J'ai essayé votre modèle en utilisant mon code comme suit. Cela fonctionne parfaitement comme 2.1, 32.5, 444.8, 564.9 etc.

Mon code: 

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");
                }
            }
        });
    }
}
0
sush