2016-04-14 11 views
1

Ich versuche eine Regex für meine EditText zu erstellen, um nur Eingaben im Dollar-Format zuzulassen. Es funktioniert jedoch nicht.Eingabefilter - Regex für zwei Dezimalstellen

public class DecimalInputFilter implements InputFilter { 

    Pattern mPattern; 

    public DecimalInputFilter() { 
     mPattern=Pattern.compile("^[0-9]+([.][0-9]{2})?$"); 
    } 

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

     Matcher matcher=mPattern.matcher(dest); 
     if(!matcher.matches()) 
      return ""; 
     return null; 
    } 

} 

Der Regex dachte Prozess -

  • Mindestens ein numerisches Zeichen
  • ein mit genau zwei numerischen Zeichen gefolgt Punkt (Optional)

Wenn ich versuche, dies zu beantragen, Ich kann keine Zahlen eingeben. Was vermisse ich?

Antwort

3

Was auch immer Sie in der editText eingeben, erhalten Sie die CharSequence in Quelle und Ihr bereits in dest eingegebene Zeichenkette, so stattdessen versuchen

Matcher matcher=mPattern.matcher(dest.toString() + source.toString()); 

und verwenden Sie die Regex als ^[0-9]+([.][0-9]{0,2})?$

Die Über Regex wird auch außer 4. Aber es kann nichts getan werden, da wir nur ein Zeichen gleichzeitig eingeben können. Um darauf zu achten, können Sie nach dem Übergeben des Wertes eine abschließende Regex-Prüfung durchführen.

+0

macht Sinn, aber das OP sagt, er kann nicht einmal eine Nummer eingeben ... – sweaver2112

+0

@RickSanchez nein, es schlägt immer noch die Streichhölzer überprüfen. – Alan

+0

@Alan Sie können nur Zahlen eingeben, oder? –

0

Wenn Sie schreiben

Matcher matcher=mPattern.matcher(dest); 
if(!matcher.matches()) 
    return ""; 

Es bedeutet, dass alle Ihre Eingabe mit "" ersetzt wird, wenn Ihr Text bearbeiten mit Ihrem regex nicht abgestimmt ist, die, nehme ich an, ist der Fall zunächst, da es wahrscheinlich eine leere Zeichenfolge ist .

+0

würde der Filter nicht nur laufen, wenn er eine Eingabe erhält? – sweaver2112

+0

@ sweaver2112, ja, aber er passt es gegen das Ziel spannbar, das noch nicht geändert wird. – satorikomeiji

-2

Ich nehme an, Sie erleben dies, weil Ihr Filter die Eingabe für jedes eingegebene Symbol verarbeitet und bis Sie alle Symbole eingeben, die Ihre Regexp einfach nicht mit der Eingabe übereinstimmen. Wenn Sie versuchen, die allerersten Symbole einzugeben, sagen wir, es ist "2", stimmt es nicht mit dem gesamten regulären Ausdruck überein. Sie müssen also entweder Ihre Regexp ändern und Punkt- und Dezimalteile davon optional machen, oder Sie müssen den Filter auf eine etwas explizitere Weise anwenden, wenn die Eingabe abgeschlossen ist (wie bei "Senden/Anwenden" Button Klick Aktion).

Als eine Randnotiz, verwenden Sie android:inputType Attribut für Ihre EditText Element, in 9 von 10 Fällen deckt es alle Ihre Bedürfnisse bei der Filterung der Eingabe ab; in meinem Fall schlage ich vor, dass Sie den Typ "numberDecimal" verwenden.

EDIT: bewusst sein, dass, obwohl Ihr regexp den Dezimalteil des Eingangs als optional markiert, Matcher.matches() Methode gibt true nur dann, wenn es den gesamten regulären Ausdruck übereinstimmt.

Von Matcher Klasse JavaDoc:

Tries das Muster gegen die gesamte Region anzupassen (oder den gesamten Eingang, wenn keine Region gesetzt wurde). Gibt true zurück, wenn (und nur wenn) das Muster der gesamten Region entspricht.

+0

aber mache ich es nicht schon optional mit dem '?' Am Ende des Dezimalausdrucks – Alan

+0

@Alan: yup, die Regex selbst scheint in Ordnung. Es wird mit einer "2" übereinstimmen. – sweaver2112

+0

Wenn Sie und andere Leute, die mich ablehnen, die Dokumentation sorgfältig lesen, würden Sie sehen, dass die Methode matches() "true zurückgibt, wenn (und nur wenn) das Muster der gesamten Region entspricht." –

1

Sie können folgende Filter ausprobieren, MAX_NUMBER verwenden, um die maximale Anzahl von Stellen vor dem Punkt zu setzen und PRECISION die genaue Zahl nach dem Punkt zu setzen.

public class DecimalInputFilter implements InputFilter { 
    private static final int MAX_NUMBER = 10; 
    private static final int PRECISION = 2; 

    public DecimalInputFilter() { 
    } 

    @Override 
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { 
     StringBuilder builder = new StringBuilder(dest); 
     builder.replace(dstart, dend, source.subSequence(start, end).toString()); 

     if (!builder.toString().matches("(([0-9]{1})([0-9]{0,"+(MAX_NUMBER-1)+"})?)?(\\.[0-9]{0,"+PRECISION+"})?")) { 
      if(source.length() == 0) 
       return dest.subSequence(dstart, dend); 
      return ""; 
     } 

     return null; 
    } 
} 
+0

das funktioniert, können Sie die Regex und die 'Builder.replace' erklären? – Alan

+1

Für die Regex, der erste Teil fragt nach mindestens einer Zahl, der zweite Teil ermöglicht die Eingabe von 0 bis MAX_NUMBER zusätzliche Zahlen und der letzte Teil erlaubt die Eingabe von 2 Ziffern nach dem Komma, aber auch keine Ziffern ist erlaubt (dh 20/20.1/20.12 sind erlaubt). Bezüglich des Ersatzes erinnere ich mich nicht klar, ich hätte diesen Teil vielleicht von einer anderen SO-Frage übernommen, es gibt vielleicht einen Weg, es einfacher zu machen ... –

+0

@Alan Du weißt, es ist wirklich seltsam, in deiner Frage hast du gefragt Was Sie vielleicht vermissen und ich habe Ihnen die richtige Erklärung gegeben, was genau Sie vermissen, aber Sie wählen nur die Antwort, die "funktioniert" und nicht einmal daran interessiert, was genau Sie vermisst haben und warum Ihr Code nicht für Sie funktioniert hat. –

1

Verwenden Sie die nächste Filterfunktion:

public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { 
    if (source.equals("")) return null; // Para el backspace 
    StringBuilder builder = new StringBuilder(dest); 
    builder.replace(dstart, dend, source.subSequence(start, end).toString()); 
    Matcher matcher=mPattern.matcher(builder); 
    if(!matcher.matches()) 
     return ""; 
    return null; 
} 

Denn wenn man auf Builder übereinstimmen lassen Sie wissen, ob die letzte Zeichenfolge, die den vorgeschlagenen Ausdruck übereinstimmt, sonst ist es die leere Zeichenkette zurückgibt.

Verwandte Themen