Gibt es eine Möglichkeit, einen Min- und Max-Wert für EditText in Android zu definieren?

133

Ich möchte einen Min- und Max-Wert für ein definieren EditText.

Beispiel: Wenn eine Person versucht, einen Monatswert einzugeben, muss der Wert zwischen 1 und 12 liegen.

Ich kann es mit verwenden, TextWatcheraber ich möchte wissen, ob es eine andere Möglichkeit gibt, dies in der Layoutdatei oder anderswo zu tun.

Bearbeiten: Ich möchte die Anzahl der Zeichen nicht begrenzen. Ich möchte den Wert begrenzen. Wenn ich beispielsweise EditTextbei der Eingabe von 12 Zeichen für Monat w beschränke , wird dies akzeptiert. Wenn ich jedoch 22 Zeichen eingebe, darf dies bei der Eingabe nicht akzeptiert werden.

mertaydin
quelle
Jemand sollte eine Bibliothek / Sammlung all dieser Arten von Eingabefiltern erstellen. Dann kann jeder gemeinsam arbeiten und testen. Anstatt dass jeder sein eigenes Ding macht.
Zapnologica
Verwenden Sie diesen Textbearbeitungsfilter, um Ihr Problem zu lösen. Filter
Taras Smakula

Antworten:

286

Machen Sie zuerst diese Klasse:

package com.test;

import android.text.InputFilter;
import android.text.Spanned;

public class InputFilterMinMax implements InputFilter {

    private int min, max;

    public InputFilterMinMax(int min, int max) {
        this.min = min;
        this.max = max;
    }

    public InputFilterMinMax(String min, String max) {
        this.min = Integer.parseInt(min);
        this.max = Integer.parseInt(max);
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {   
        try {
            int input = Integer.parseInt(dest.toString() + source.toString());
            if (isInRange(min, max, input))
                return null;
        } catch (NumberFormatException nfe) { }     
        return "";
    }

    private boolean isInRange(int a, int b, int c) {
        return b > a ? c >= a && c <= b : c >= b && c <= a;
    }
}

Verwenden Sie dann dies aus Ihrer Aktivität:

EditText et = (EditText) findViewById(R.id.myEditText);
et.setFilters(new InputFilter[]{ new InputFilterMinMax("1", "12")});

Dadurch kann der Benutzer nur Werte von 1 bis 12 eingeben .

EDIT:

Stellen Sie Ihren Edittext mit ein android:inputType="number".

Weitere Informationen finden Sie unter https://www.techcompose.com/how-to-set-minimum-and-maximum-value-in-edittext-in-android-app-development/ .

Vielen Dank.

Pratik Sharma
quelle
1
@mertaydin sicher. Probieren Sie es aus und lassen Sie mich wissen, wenn Sie meine Hilfe benötigen. Vielen Dank.
Pratik Sharma
12
Aah, ich brauche Hilfe. Ich habe ein Problem beim Schreiben eines Werts zwischen 1930 und 1999. Wenn ich 1 schreibe, steuert es den Wert und 1 ist nicht zwischen 1930 und 1999, also akzeptiert es ihn nicht.
Mertaydin
1
@mertaydin Hey sorry, aber ich war ein bisschen beschäftigt mit meiner Arbeit. Ich habe gerade etwas Zeit, um mich damit zu befassen. Ich denke, ich muss Änderungen an dem in der Filterklasse angewendeten Algorithmus vornehmen. Ich werde dich aktualisieren, sobald ich damit fertig bin.
Pratik Sharma
1
Einige Zeichen von sourceersetzen einige Zeichen in dest. Ich denke, Sie sollten den Austausch simulieren und das Endergebnis erhalten und es dann validieren.
SD
3
@Pratik Sharma, Dies funktioniert nicht, wenn ich den Bereich von 1900 bis 2000
betrete.
89

Es gibt einen kleinen Fehler in Pratiks Code. Wenn beispielsweise ein Wert 10 ist und Sie zu Beginn eine 1 hinzufügen, um 110 zu erhalten, behandelt die Filterfunktion den neuen Wert als 101.

Eine Lösung hierfür finden Sie weiter unten:

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    try {
        // Remove the string out of destination that is to be replaced
        String newVal = dest.toString().substring(0, dstart) + dest.toString().substring(dend, dest.toString().length());
        // Add the new string in
        newVal = newVal.substring(0, dstart) + source.toString() + newVal.substring(dstart, newVal.length());
        int input = Integer.parseInt(newVal);
        if (isInRange(min, max, input))
            return null;
    } catch (NumberFormatException nfe) { }
    return "";
}
Zac
quelle
Danke, das hat mir sehr geholfen!
Joschplusa
4
Ich denke, das ist klarer imho :String replacement = source.subSequence(start, end).toString(); String newVal = dest.subSequence(0, dstart).toString() + replacement + dest.subSequence(dend, dest.length()).toString();
Sven Jacobs
1
+1. Diese Lösung ist korrekter als akzeptiert. Um dies zu überprüfen, versuchen Sie beispielsweise, InputFilterMinMax mit aktivierter Option selectAllOnFocus zu verwenden und das Ergebnis zu vergleichen.
Sash0k
1
Warum nicht String newVal= dest.toString().substring(0, dstart) + source.toString().substring(start, end) + dest.toString().substring(dend, dest.toString().length());, sieht sauberer und klarer aus.
Shishir Gupta
5
Wie von OP @mertaydin in einem Kommentar zu @Patricks Antwort erwähnt, weist diese Lösung immer noch einen großen Fehler auf. Ich frage mich, warum sie nicht gemeldet wurde: Wenn es min==3dann unmöglich ist, eine Zahl einzugeben, die mit 1 oder 2 beginnt (Beispiel: 15, 23)
Guerneen4
10

Von dem, was ich von @ Patriks Lösung und @ Zacs Hinzufügung gesehen habe, hat der bereitgestellte Code immer noch ein großes Problem:

Wenn es min==3dann unmöglich ist, eine Zahl einzugeben, die mit 1 oder 2 beginnt (Beispiel: 15, 23).
Wenn es min>=10dann unmöglich ist, etwas einzugeben, da jede Zahl mit 1,2,3 beginnen muss ...

Nach meinem Verständnis können wir die Min-Max-Begrenzung des EditTextWerts von a nicht durch einfache Verwendung der Klasse erreichen InputFilterMinMax, zumindest nicht für den Min-Wert, da der Wert wächst, wenn der Benutzer eine positive Zahl eingibt, und wir leicht eine ausführen können On-the-Fly-Test, um zu überprüfen, ob das Limit erreicht wurde oder außerhalb des Bereichs liegt, und Einträge zu blockieren, die nicht den Anforderungen entsprechen. Das Testen des Mindestwerts ist eine andere Geschichte, da wir nicht sicher sein können, ob der Benutzer die Eingabe beendet hat oder nicht, und daher nicht entscheiden können, ob wir blockieren sollen oder nicht.

Es ist nicht genau das, was OP angefordert hat, aber zu Validierungszwecken habe ich in meiner Lösung kombiniert InputFilter, OnFocusChangeListenerum Maximalwerte zu testen, mit einem erneuten Test für Minimalwerte, wenn EditTextder Fokus verloren geht, vorausgesetzt, der Benutzer hat die Eingabe beendet und es ist ungefähr so:

package test;


import android.text.InputFilter;

import android.text.Spanned;

public class InputFilterMax implements InputFilter {

private int max;

public InputFilterMax(int max) {
    this.max = max;
}

public InputFilterMax(String max) {
    this.max = Integer.parseInt(max);
}

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {   
    try {
        String replacement = source.subSequence(start, end).toString(); 

        String newVal = dest.toString().substring(0, dstart) + replacement +dest.toString().substring(dend, dest.toString().length());

        int input = Integer.parseInt(newVal);

        if (input<=max)
            return null;
    } catch (NumberFormatException nfe) { }   
//Maybe notify user that the value is not good      
return "";
}
}

Und OnFocusChangeListenerMin

package test;

import android.text.TextUtils;
import android.view.View;
import android.view.View.OnFocusChangeListener;

public class OnFocusChangeListenerMin implements OnFocusChangeListener {

private int min;

public OnFocusChangeListenerMin(int min) {
    this.min = min;
}

public OnFocusChangeListenerMin(String min) {
    this.min = Integer.parseInt(min);
}


@Override
public void onFocusChange(View v, boolean hasFocus) {
    if(!hasFocus) {
        String val = ((EditText)v).getText().toString();
        if(!TextUtils.isEmpty(val)){
            if(Integer.valueOf(val)<min){
                //Notify user that the value is not good
            }

        }
    }
}
}

Stellen Sie dann in Aktivität das InputFilterMaxund das OnFocusChangeListenerMinzu EditText beachtende ein: Sie können 2 sowohl min als auch max in onFocusChangeListener.

mQteEditText.setOnFocusChangeListener( new OnFocusChangeListenerMin('20');
mQteEditText.setFilters(new InputFilter[]{new InputFilterMax(getActivity(),'50')});
Guerneen4
quelle
OnFocusChangeListenerMin funktioniert nicht, es setzt alle Werte von Null
EminenT
1
Würde es Ihnen etwas ausmachen, ein bisschen mehr zu detaillieren? Was meinst du damit , alle Werte von Null zu setzen ?
Guerneen4
vom Code OnFocusChangeListenerMin muss über 20 arbeiten, wie im Problem beschrieben, aber es akzeptiert alle Werte unter 20 wie 0, 1, 2, ------ 19 usw.
EminenT
Hast du eine Lösung gefunden?
EminenT
Ich habe OnFoncusChangeListener zu Validierungszwecken verwendet. In meinem Fall wird bei EditText ein Fehler angezeigt. Benachrichtigen Sie den Benutzer durch einen Toast, dass der Wert nicht gut ist, und fordern Sie ihn auf, einen neuen Wert einzugeben. if(Integer.valueOf(val)<min){ //Notify user that the value is not good } Sie können dort tun, was Sie möchten Benutzer und setzen Sie EditText auf leer, ich weiß nicht, ob dies Ihre Frage beantwortet
Guerneen4
9

Erweiterung der Antwort von Pratik und Zac. Zac hat einen kleinen Fehler von Pratik in seiner Antwort behoben. Ich habe jedoch festgestellt, dass Code keine negativen Werte unterstützt, sondern eine NumberFormatException auslöst. Verwenden Sie den folgenden Code, um dies zu beheben und zuzulassen, dass der MIN negativ ist.

Fügen Sie diese Zeile (fett) zwischen die beiden anderen Zeilen ein:

newVal = newVal.substring (0, dstart) + source.toString () + newVal.substring (dstart, newVal.length ());

if (newVal.equalsIgnoreCase ("-") && min <0) return null;

int input = Integer.parseInt (newVal);

public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    try {
        // Remove the string out of destination that is to be replaced
        String newVal = dest.toString().substring(0, dstart) + dest.toString().substring(dend, dest.toString().length());
        // Add the new string in
        newVal = newVal.substring(0, dstart) + source.toString() + newVal.substring(dstart, newVal.length());
        //****Add this line (below) to allow Negative values***// 
        if(newVal.equalsIgnoreCase("-") && min < 0)return null;
        int input = Integer.parseInt(newVal);
        if (isInRange(min, max, input))
            return null;
    } catch (NumberFormatException nfe) {
        nfe.printStackTrace();
    }
    return "";
}
Anthony B.
quelle
5

Wenn Sie einen Bereich mit negativen Zahlen wie -90: 90 benötigen, können Sie diese Lösung verwenden.

public class InputFilterMinMax implements InputFilter {

private int min, max;

public InputFilterMinMax(int min, int max) {
    this.min = min;
    this.max = max;
}

public InputFilterMinMax(String min, String max) {
    this.min = Integer.parseInt(min);
    this.max = Integer.parseInt(max);
}

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    try {
        String stringInput = dest.toString() + source.toString();
        int value;
        if (stringInput.length() == 1 && stringInput.charAt(0) == '-') {
            value = -1;
        } else {
            value = Integer.parseInt(stringInput);
        }
        if (isInRange(min, max, value))
            return null;
    } catch (NumberFormatException nfe) {
    }
    return "";
}

private boolean isInRange(int min, int max, int value) {
    return max > min ? value >= min && value <= max : value >= max && value <= min;
}
}
Denys Vasylenko
quelle
5

Ich habe den @ Ratik Sharmas-Code erweitert, um BigDecimal-Objekte anstelle von Ints zu verwenden, damit größere Zahlen akzeptiert werden können, und alle Formatierungen im EditText zu berücksichtigen, die keine Zahlen sind (wie Währungsformatierungen, dh Leerzeichen, Kommas und Punkte).

BEARBEITEN: Beachten Sie, dass diese Implementierung 2 als minimale signifikante Zahlen hat, die auf der BigDecimal festgelegt wurden (siehe die Konstante MIN_SIG_FIG), da ich sie für die Währung verwendet habe, sodass immer 2 führende Zahlen vor dem Dezimalpunkt standen. Ändern Sie die Konstante MIN_SIG_FIG nach Bedarf für Ihre eigene Implementierung.

public class InputFilterMinMax implements InputFilter {
private static final int MIN_SIG_FIG = 2;
private BigDecimal min, max;

public InputFilterMinMax(BigDecimal min, BigDecimal max) {
    this.min = min;
    this.max = max;
}

public InputFilterMinMax(String min, String max) {
    this.min = new BigDecimal(min);
    this.max = new BigDecimal(max);
}

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart,
        int dend) {
    try {
        BigDecimal input = formatStringToBigDecimal(dest.toString()
                + source.toString());

        if (isInRange(min, max, input)) {

            return null;
        }
    } catch (NumberFormatException nfe) {

    }
    return "";
}

private boolean isInRange(BigDecimal a, BigDecimal b, BigDecimal c) {
    return b.compareTo(a) > 0 ? c.compareTo(a) >= 0 && c.compareTo(b) <= 0
            : c.compareTo(b) >= 0 && c.compareTo(a) <= 0;
}

public static BigDecimal formatStringToBigDecimal(String n) {

    Number number = null;
    try {
        number = getDefaultNumberFormat().parse(n.replaceAll("[^\\d]", ""));

        BigDecimal parsed = new BigDecimal(number.doubleValue()).divide(new BigDecimal(100), 2,
                BigDecimal.ROUND_UNNECESSARY);
        return parsed;
    } catch (ParseException e) {
        return new BigDecimal(0);
    }
}

private static NumberFormat getDefaultNumberFormat() {
    NumberFormat nf = NumberFormat.getInstance(Locale.getDefault());
    nf.setMinimumFractionDigits(MIN_SIG_FIG);
    return nf;
}
AndroidNoob
quelle
4

Ich habe meine eigene Antwort gefunden. Es ist jetzt sehr spät, aber ich möchte es mit Ihnen teilen. Ich implementiere diese Schnittstelle:

import android.text.TextWatcher;


public abstract class MinMaxTextWatcher implements TextWatcher {
    int min, max;
    public MinMaxTextWatcher(int min, int max) {
        super();
        this.min = min;
        this.max = max;
    }

}

Und implementieren Sie es dann folgendermaßen in Ihre Aktivität:

private void limitEditText(final EditText ed, int min, int max) {
    ed.addTextChangedListener(new MinMaxTextWatcher(min, max) {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

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

        }

        @Override
        public void afterTextChanged(Editable s) {
            String str = s.toString();
            int n = 0;
            try {
                n = Integer.parseInt(str);
                if(n < min) {
                    ed.setText(min);
                    Toast.makeText(getApplicationContext(), "Minimum allowed is " + min, Toast.LENGTH_SHORT).show();
                }
                else if(n > max) {
                    ed.setText("" + max);
                    Toast.makeText(getApplicationContext(), "Maximum allowed is " + max, Toast.LENGTH_SHORT).show();
                }
            }
            catch(NumberFormatException nfe) {
                ed.setText("" + min);
                Toast.makeText(getApplicationContext(), "Bad format for number!" + max, Toast.LENGTH_SHORT).show();
            }
        }
    });
}

Dies ist eine sehr einfache Antwort. Wenn es besser ist, sagen Sie es mir bitte.

Nash Makineta
quelle
int n = 0; ist redundant. Da der Standardwert von n 0 ist.
Kenny Dabiri
1
Warum ist int n = 0 hier redundant? Es ist eine lokale Variable und hier keine Instanzvariable.
User12111111
4

In der akzeptierten Antwort stimmt etwas nicht.

int input = Integer.parseInt(dest.toString() + source.toString());

Wenn ich den Cursor in die Mitte des Textes bewege und dann etwas eingebe, führt die obige Anweisung zu einem falschen Ergebnis. Geben Sie beispielsweise zuerst "12" und dann "0" zwischen 1 und 2 ein. Die oben genannte Anweisung erzeugt dann "120" anstelle von 102. Ich habe diese Anweisung in die folgenden Anweisungen geändert:

String destString = dest.toString();
  String inputString = destString.substring(0, dstart) + source.toString() + destString.substring(dstart);
  int input = Integer.parseInt(inputString);
谭春茂
quelle
4

Kotlin, wenn jemand es braucht (Use Utilities)

class InputFilterMinMax: InputFilter {
    private var min:Int = 0
    private var max:Int = 0
    constructor(min:Int, max:Int) {
        this.min = min
        this.max = max
    }
    constructor(min:String, max:String) {
        this.min = Integer.parseInt(min)
        this.max = Integer.parseInt(max)
    }
    override fun filter(source:CharSequence, start:Int, end:Int, dest: Spanned, dstart:Int, dend:Int): CharSequence? {
        try
        {
            val input = Integer.parseInt(dest.toString() + source.toString())
            if (isInRange(min, max, input))
                return null
        }
        catch (nfe:NumberFormatException) {}
        return ""
    }
    private fun isInRange(a:Int, b:Int, c:Int):Boolean {
        return if (b > a) c in a..b else c in b..a
    }
}

Verwenden Sie dies dann aus Ihrer Kotlin-Klasse

percentage_edit_text.filters = arrayOf(Utilities.InputFilterMinMax(1, 100))

Dieser EditText erlaubt 1 bis 100.

Verwenden Sie dies dann aus Ihrem XML

android:inputType="number"
Alish
quelle
Ich benutze die Rückgabequelle und arbeite für mich ==> if (isInRange (min, max, input)) Rückgabequelle
Muzafferus
3

Ich habe es einfacher gemacht, ein Min / Max auf einen Edittext zu setzen. Ich benutze die arithmetische Tastatur und arbeite mit dieser Methode:

 private int limit(EditText x,int z,int limin,int limax){

    if( x.getText().toString()==null || x.getText().toString().length()==0){
        x.setText(Integer.toString(limin));
        return z=0;
    }
    else{
        z = Integer.parseInt(x.getText().toString());
         if(z <limin || z>limax){
             if(z<10){
                 x.setText(Integer.toString(limin));
                return  z=0;
             }
            else{
                x.setText(Integer.toString(limax));
                return z=limax;
            }

         }
         else
            return z = Integer.parseInt(x.getText().toString());
    }
 }

Die Methode akzeptiert alle Ihre Werte, aber wenn ein Wert von Benutzern Ihre Grenzwerte nicht einhält, wird er automatisch auf das Min / Max-Limit gesetzt. Zum Beispiel. limit limin = 10, limax = 80 wenn der Benutzer 8 setzt, wird automatisch 10 in einer Variablen gespeichert und EditText wird auf 10 gesetzt.

Argyris
quelle
3

Ich weiß, dass es bereits eine Million Antworten darauf gibt, von denen eine akzeptiert wird. Die akzeptierte Antwort enthält jedoch zahlreiche Fehler, und die meisten anderen beheben einfach einen (oder möglicherweise zwei) von ihnen, ohne auf alle möglichen Anwendungsfälle auszuweiten.

Daher habe ich im Grunde genommen die meisten in den Support-Antworten vorgeschlagenen Fehlerkorrekturen zusammengestellt und eine Methode hinzugefügt, mit der Zahlen außerhalb des Bereichs kontinuierlich in Richtung 0 eingegeben werden können (wenn der Bereich nicht bei 0 beginnt), zumindest bis dies der Fall ist sicher, dass es nicht mehr im Bereich sein kann. Denn um klar zu sein, ist dies das einzige Mal, dass bei vielen anderen Lösungen wirklich Probleme auftreten.

Hier ist das Update:

public class InputFilterIntRange implements InputFilter, View.OnFocusChangeListener {

    private final int min, max;

    public InputFilterIntRange(int min, int max) {
        if (min > max) {
            // Input sanitation for the filter itself
            int mid = max;
            max = min;
            min = mid;
        }
        this.min = min;
        this.max = max;
    }

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

        // Determine the final string that will result from the attempted input
        String destString = dest.toString();
        String inputString = destString.substring(0, dstart) + source.toString() + destString.substring(dstart);

        // Don't prevent - sign from being entered first if min is negative
        if (inputString.equalsIgnoreCase("-") && min < 0) return null;

        try {
            int input = Integer.parseInt(inputString);
            if (mightBeInRange(input))
                return null;
        } catch (NumberFormatException nfe) {}

        return "";
    }

    @Override
    public void onFocusChange(View v, boolean hasFocus) {

        // Since we can't actively filter all values
        // (ex: range 25 -> 350, input "15" - could be working on typing "150"),
        // lock values to range after text loses focus
        if (!hasFocus) {
            if (v instanceof EditText) sanitizeValues((EditText) v);
        }
    }

    private boolean mightBeInRange(int value) {
        // Quick "fail"
        if (value >= 0 && value > max) return false;
        if (value >= 0 && value >= min) return true;
        if (value < 0 && value < min) return false;
        if (value < 0 && value <= max) return true;

        boolean negativeInput = value < 0;

        // If min and max have the same number of digits, we can actively filter
        if (numberOfDigits(min) == numberOfDigits(max)) {
            if (!negativeInput) {
                if (numberOfDigits(value) >= numberOfDigits(min) && value < min) return false;
            } else {
                if (numberOfDigits(value) >= numberOfDigits(max) && value > max) return false;
            }
        }

        return true;
    }

    private int numberOfDigits(int n) {
        return String.valueOf(n).replace("-", "").length();
    }

    private void sanitizeValues(EditText valueText) {
        try {
            int value = Integer.parseInt(valueText.getText().toString());
            // If value is outside the range, bring it up/down to the endpoint
            if (value < min) {
                value = min;
                valueText.setText(String.valueOf(value));
            } else if (value > max) {
                value = max;
                valueText.setText(String.valueOf(value));
            }
        } catch (NumberFormatException nfe) {
            valueText.setText("");
        }
    }

}

Beachten Sie, dass einige Eingabefälle nicht "aktiv" behandelt werden können (dh wenn der Benutzer sie eingibt). Daher müssen wir sie ignorieren und behandeln, nachdem der Benutzer den Text bearbeitet hat.

So können Sie es verwenden:

EditText myEditText = findViewById(R.id.my_edit_text);
InputFilterIntRange rangeFilter = new InputFilterIntRange(25, 350);
myEditText.setFilters(new InputFilter[]{rangeFilter});

// Following line is only necessary if your range is like [25, 350] or [-350, -25].
// If your range has 0 as an endpoint or allows some negative AND positive numbers, 
// all cases will be handled pre-emptively.
myEditText.setOnFocusChangeListener(rangeFilter);

Wenn der Benutzer nun versucht, eine Zahl einzugeben, die näher an 0 liegt, als es der Bereich zulässt, geschieht eines von zwei Dingen:

  1. Wenn minund maxdie gleiche Anzahl von Ziffern haben, dürfen sie diese nicht mehr eingeben, sobald sie die letzte Ziffer erreicht haben.

  2. Wenn eine Zahl außerhalb des Bereichs im Feld verbleibt, wenn der Text den Fokus verliert, wird er automatisch an die nächstgelegene Grenze angepasst.

Und natürlich darf der Benutzer niemals einen Wert eingeben, der weiter von 0 entfernt ist, als es der Bereich zulässt, und es ist aus diesem Grund auch nicht möglich, dass sich eine solche Zahl "versehentlich" im Textfeld befindet.

Bekannte Probleme?)

  1. Dies funktioniert nur, wenn der EditTextFokus verloren geht, wenn der Benutzer damit fertig ist.

Die andere Option ist die Bereinigung, wenn der Benutzer die Taste "Fertig" / "Zurück" drückt. In vielen oder sogar den meisten Fällen führt dies jedoch zu einem Fokusverlust.

Durch Schließen der Softtastatur wird das Element jedoch nicht automatisch unscharf. Ich bin mir sicher, dass 99,99% der Android-Entwickler dies wünschen (und dass der Fokus auf EditTextElemente im Allgemeinen weniger ein Sumpf war), aber bis jetzt gibt es keine eingebaute Funktionalität dafür. Die einfachste Methode, die ich gefunden habe, um dies zu umgehen, besteht darin, EditTextFolgendes zu erweitern :

public class EditTextCloseEvent extends AppCompatEditText {

    public EditTextCloseEvent(Context context) {
        super(context);
    }

    public EditTextCloseEvent(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public EditTextCloseEvent(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            for (InputFilter filter : this.getFilters()) {
                if (filter instanceof InputFilterIntRange)
                    ((InputFilterIntRange) filter).onFocusChange(this, false);
            }
        }
        return super.dispatchKeyEvent(event);
    }
}

Dadurch wird der Filter dazu gebracht, die Eingabe zu bereinigen, obwohl die Ansicht den Fokus nicht wirklich verloren hat. Wenn die Ansicht später selbst den Fokus verliert, wird die Eingabesanierung erneut ausgelöst, aber es ändert sich nichts, da sie bereits behoben wurde.

Schließen

Wütend. Das war viel. Was ursprünglich so aussah, als wäre es ein ziemlich trivial einfaches Problem, und am Ende wurden viele kleine hässliche Teile von Vanille-Android (zumindest in Java) entdeckt. Und noch einmal, Sie müssen den Listener nur hinzufügen und erweitern, EditTextwenn Ihr Bereich in keiner Weise 0 enthält. (Und realistisch gesehen, wenn Ihr Bereich nicht 0 enthält, sondern bei 1 oder -1 beginnt, werden Sie auch nicht auf Probleme stoßen.)

Als letzte Anmerkung funktioniert dies nur für Ints . Es gibt sicherlich eine Möglichkeit, es so zu implementieren, dass es mit Dezimalstellen ( double, float) funktioniert , aber da weder ich noch der ursprüngliche Fragesteller dies benötigen, möchte ich nicht besonders tief darauf eingehen. Es wäre sehr einfach, die Filterung nach Abschluss zusammen mit den folgenden Zeilen zu verwenden:

// Quick "fail"
if (value >= 0 && value > max) return false;
if (value >= 0 && value >= min) return true;
if (value < 0 && value < min) return false;
if (value < 0 && value <= max) return true;

Sie müssten nur von intzu float(oder double) wechseln , das Einfügen eines einzelnen .(oder ,, je nach Land?) Zulassen und als einen der Dezimaltypen anstelle von a analysieren int.

Das erledigt sowieso den größten Teil der Arbeit, also würde es sehr ähnlich funktionieren.

VerumCH
quelle
2
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    try {
        String prefix = dest.toString().substring(0, dstart);
        String insert = source.toString();
        String suffix = dest.toString().substring(dend);
        String input_string = prefix + insert + suffix;
        int input = Integer.parseInt(input_string);

        if (isInRange(min, max, input) || input_string.length() < String.valueOf(min).length())
            return null;
    } catch (NumberFormatException nfe) { }
    return "";
}

private boolean isInRange(int a, int b, int c) {
    return b > a ? c >= a && c <= b : c >= b && c <= a;
}
jet27
quelle
2

Sehr einfaches Beispiel für Kotlin:

import android.text.InputFilter
import android.text.Spanned

class InputFilterRange(private var range: IntRange) : InputFilter {

    override fun filter(source: CharSequence, start: Int, end: Int, dest: Spanned, dstart: Int, dend: Int) = try {
        val input = Integer.parseInt(dest.toString() + source.toString())
        if (range.contains(input)) null else ""
    } catch (nfe: NumberFormatException) {
        ""
    }
}
Andrew
quelle
1

Bitte überprüfen Sie diesen Code

    String pass = EditText.getText().toString(); 
    if(TextUtils.isEmpty(pass) || pass.length < [YOUR MIN LENGTH]) 
    { 
       EditText.setError("You must have x characters in your txt"); 
        return; 
    }

    //continue processing



edittext.setOnFocusChangeListener( new OnFocusChangeListener() {

       @Override
       public void onFocusChange(View v, boolean hasFocus) {
          if(hasFocus) {
           // USE your code here 
  }

Verwenden Sie den folgenden Link für weitere Details zu edittext und den edittextfiltern mit Text Watcher.

http://www.mobisoftinfotech.com/blog/android/android-edittext-setfilters-example-numeric-text-field-patterns-and-length-restriction/

itsrajesh4uguys
quelle
OP möchte es validieren, wenn der Wert eingegeben wird. Ich denke, Sie haben eine Lösung für das Szenario bereitgestellt, nachdem der Wert eingegeben wurde
MysticMagicϡ
Ich bin nicht der Fragesteller. Ich hatte nur Zweifel an Ihrer Antwort, also habe ich sie geklärt.
MysticMagicϡ
Ich möchte die Anzahl der Zeichen nicht überprüfen. Ich denke, Sie versuchen, die Anzahl in diesem Code zu überprüfen: if (TextUtils.isEmpty (pass) || pass.length <[IHRE MIN-LÄNGE]) Ich beschränke nur den Wert, zum Beispiel für den Monatswert, zwischen den der Benutzer den Wert schreiben muss 1-12 nicht 13,14 oder so, also 12,13,14, bis 99 2 Zeichen lang ist.
Mertaydin
Hallo @mertaydin, hast du es mit dem Link versucht, den ich dir zur Verfügung gestellt habe? Siehe dieses Beispiel. Vielleicht ist es das, was du willst. es wird den Text sehen, während Sie
eingeben
Ok, danke, ich werde deine Antwort und die Antwort von @Pratik Sharma versuchen.
Mertaydin
1

Wenn Sie nur über das maximale Limit besorgt sind, fügen Sie einfach die folgende Zeile hinzu

android:maxLength="10" 

Wenn Sie ein Mindestlimit hinzufügen müssen, können Sie dies in diesem Fall auf diese Weise tun. Das Mindestlimit beträgt 7. Der Benutzer darf nur Zeichen zwischen dem Mindest- und dem Höchstlimit (zwischen 8 und 10) eingeben.

public final static boolean isValidCellPhone(String number){
        if (number.length() < 8 || number.length() >10 ) {
            return false;
        } else {

           return android.util.Patterns.PHONE.matcher(number).matches();
        }
    }

Wenn Sie den Benutzer auch einschränken müssen, um beim Start 01 einzugeben, ändern Sie die Bedingung auf diese Weise

if (!(number.startsWith("01")) || number.length() < 8 || number.length() >10 ) {  
.
.
.
}

Am Ende Aufrufmethode wie

   ....else if (!(Helper.isValidMobilePhone(textMobileNo))){
                        Helper.setEditTextError(etMobileNo,"Invalid Mobile Number");
                    }......
Faakhir
quelle
2
Das ist kein Wert, das ist Länge
Portfoliobuilder
1

@Pratik Sharma

Fügen Sie zur Unterstützung negativer Zahlen den folgenden Code in die Filtermethode ein :

package ir.aboy.electronicarsenal;

import android.text.InputFilter;
import android.text.Spanned;

public class InputFilterMinMax implements InputFilter {

  private int min, max;
  int input;

  InputFilterMinMax(int min, int max) {
    this.min = min;
    this.max = max;
  }

  public InputFilterMinMax(String min, String max) {
    this.min = Integer.parseInt(min);
    this.max = Integer.parseInt(max);
  }

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

      if ((dest.toString() + source.toString()).equals("-")) {
        source = "-1";
      }

      input = Integer.parseInt(dest.toString() + source.toString());
      if (isInRange(min, max, input))
        return null;

    } catch (NumberFormatException ignored) {
    }
    return "";
  }

  private boolean isInRange(int a, int b, int c) {
    return b > a ? c >= a && c <= b : c >= b && c <= a;
  }

}

Verwenden Sie dann dies aus Ihrer Aktivität:

findViewById(R.id.myEditText).setFilters(new InputFilter[]{ new InputFilterMinMax(1, 12)});

Stellen Sie Ihren Edittext ein mit:

android:inputType="number|numberSigned"
Gadolf
quelle
0

// hat immer noch ein Problem, aber hier können Sie min, max in jedem Bereich (positiv oder negativ) verwenden.

// in filter calss
 @Override
 public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        try {
            // Remove the string out of destination that is to be replaced
            int input;
            String newVal = dest.toString() + source.toString();
            if (newVal.length() == 1 && newVal.charAt(0) == '-') {
                input = min; //allow
            }
            else {
                newVal = dest.toString().substring(0, dstart) + dest.toString().substring(dend, dest.toString().length());
                // Add the new string in
                newVal = newVal.substring(0, dstart) + source.toString() + newVal.substring(dstart, newVal.length());
                input = Integer.parseInt(newVal);
            }

            //int input = Integer.parseInt(dest.toString() + source.toString());

            if (isInRange(min, max, input))
                return null;
        } catch (NumberFormatException nfe) {
        }
        return "";
    }

//also the filler must set as below: in the edit createview
// to allow enter number and backspace.
et.setFilters(new InputFilter[]{new InputFilterMinMax(min >= 10 ?  "0" : String.valueOf(min), max >-10 ? String.valueOf(max) :"0" )});



//and at same time must check range in the TextWatcher()
et.addTextChangedListener(new
 TextWatcher() {

      @Override
      public void afterTextChanged (Editable editable)
      {
         String tmpstr = et.getText().toString();
         if (!tmpstr.isEmpty() && !tmpstr.equals("-") ) {
             int datavalue = Integer.parseInt(tmpstr);
             if ( datavalue >= min || datavalue <= max) {
               // accept data ...     
             }
         }
      }
 });
CHTsai
quelle
0

Um die Antwort von Pratik zu ergänzen, gibt es hier eine modifizierte Version, in der der Benutzer mindestens 2 Ziffern eingeben kann, z. B. 15 bis 100:

 import android.text.InputFilter;
 import android.text.Spanned;

public class InputFilterMinMax implements InputFilter {

    private int min, max;

    public InputFilterMinMax(int min, int max) {
        this.min = min;
        this.max = max;
    }

    public InputFilterMinMax(String min, String max) {
        this.min = Integer.parseInt(min);
        this.max = Integer.parseInt(max);
    }

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

        try {
            if(end==1)
                min=Integer.parseInt(source.toString());
            int input = Integer.parseInt(dest.toString() + source.toString());
            if (isInRange(min, max, input))
                return null;
        } catch (NumberFormatException nfe) {
        }
        return "";
    }

    private boolean isInRange(int a, int b, int c) {

        return b > a ? c >= a && c <= b : c >= b && c <= a;
    }}

hinzugefügt: if (end == 1) min = Integer.parseInt (source.toString ());

Hoffe das hilft. Bitte stimmen Sie nicht ohne Grund ab.

Sanjeeb
quelle
0

So habe ich es benutzt, es funktioniert für negative Zahlen

Erstellen Sie zunächst die MinMaxFIlter.java-Klasse mit dem folgenden Code:

import android.text.InputFilter;
import android.text.Spanned;
import android.util.Log;

/**
* Created by 21 on 4/5/2016.
*/
public class MinMaxFilter implements InputFilter {

private double mIntMin, mIntMax;

public MinMaxFilter(double minValue, double maxValue) {
    this.mIntMin = minValue;
    this.mIntMax = maxValue;
}

public MinMaxFilter(String minValue, String maxValue) {
    this.mIntMin = Double.parseDouble(minValue);
    this.mIntMax = Double.parseDouble(maxValue);
}

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    try {
        Boolean isNeg = false;
        String provi = dest.toString() + source.toString();
        if("-".equals(provi.substring(0,1))){
            if(provi.length()>1) {
                provi = provi.substring(1, provi.length());
                isNeg = true;
            }
            else{
                if("".equals(source)){
                    return null;
                }
                return "-";
            }
        }

        double input = Double.parseDouble(provi); 
        if(isNeg){input = input * (-1);}

        if (isInRange(mIntMin, mIntMax, input)) {
            return null;
        }
    } catch (Exception nfe) {}
    return "";
}

private boolean isInRange(double a, double b, double c) {
    if((c>=a && c<=b)){
        return true;
    }
    else{
        return false;
    }
}
}

Erstellen Sie dann Ihren Filter und stellen Sie ihn wie folgt auf Ihren Edittext ein:

EditText edittext = new EditText(context);
editext.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED);
eInt.setFilters(new InputFilter[]{new MinMaxFilter(min, max)});
Maloromano
quelle
0

Das ist mein Code max = 100, min = 0

xml

<TextView
                    android:id="@+id/txt_Mass_smallWork"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textColor="#000"
                    android:textSize="20sp"
                    android:textStyle="bold" />

Java

EditText ed = findViewById(R.id.txt_Mass_smallWork);
    ed.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {`

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            if(!charSequence.equals("")) {
                int massValue = Integer.parseInt(charSequence.toString());
                if (massValue > 10) {
                    ed.setFilters(new InputFilter[]{new InputFilter.LengthFilter(2)});
                } else {
                    ed.setFilters(new InputFilter[]{new InputFilter.LengthFilter(3)});
                }
            }
        }

        @Override
        public void afterTextChanged(Editable editable) {

        }
    });
Hoàng
quelle
0

Sie können dies mit einem InputFilter tun. Anscheinend gibt es nur diese Eingangsfilterschnittstelle, die Sie verwenden können. Bevor Sie es auf nervige Weise tun und eine neue Klasse erstellen, die den Eingabefilter erweitert, können Sie diese Verknüpfung mit einer Schnittstelleninstanziierung der inneren Klasse verwenden.

Deshalb machst du einfach folgendes:

EditText subTargetTime = (EditText) findViewById(R.id.my_time);
subTargetTime.setFilters( new InputFilter[] {
                new InputFilter() {
                    @Override
                    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
                        int t = Integer.parseInt(source.toString());
                        if(t <8) { t = 8; }
                        return t+"";

                    }
                }
        });

In diesem Beispiel überprüfe ich, ob der Wert des EditText größer als 8 ist. Wenn nicht, soll er auf 8 gesetzt werden. Daher müssen Sie sich anscheinend selbst mit dem Min-Max oder einer beliebigen Filterlogik auseinandersetzen. Aber zumindest können Sie die Filterlogik ziemlich ordentlich und kurz direkt in den EditText schreiben.

Hoffe das hilft

Christopher-Robin Fey Feysenbe
quelle
0

Um den Mindestwert des EditText zu definieren, habe ich Folgendes verwendet:

if (message.trim().length() >= 1 && message.trim().length() <= 12) {
  // do stuf
} else {
  // Too short or too long
}
Bonne Bogaert
quelle
0

@ Patriks Code hat eine nette Idee, aber mit vielen Fehlern. @Zac und @Anthony B (Lösungen mit negativen Zahlen) haben einige von ihnen gelöst, aber der Code von @ Zac enthält immer noch 3 Bürgermeister-Fehler:

1. Wenn der Benutzer alle Einträge im EditText löscht, kann keine Nummer erneut eingegeben werden. Dies kann natürlich mit einem von EditText geänderten Listener für jedes Feld gesteuert werden, aber es macht die Schönheit der Verwendung einer gemeinsamen InputFilter-Klasse für jedes Feld zunichte EditText in Ihrer App.

2. Hat @ Guernee4 gesagt, wenn zum Beispiel min = 3 ist, ist es unmöglich, eine Zahl einzugeben, die mit 1 beginnt.

3. Wenn zum Beispiel min = 0 ist, können Sie viele Nullen eingeben, die Sie wünschen, dass das Ergebnis nicht elegant ist. Unabhängig davon, wie hoch der Mindestwert ist, kann der Benutzer den Cursor auf die linke Größe der ersten Zahl setzen, eine Reihe führender Nullen nach links, die ebenfalls nicht elegant sind.

Ich bin auf diese kleinen Änderungen von @ Zacs Code gekommen, um diese 3 Fehler zu beheben. In Bezug auf Fehler Nr. 3 konnte ich immer noch nicht alle führenden Nullen auf der linken Seite vollständig entfernen. Es kann immer eins sein, aber ein 00, 01, 0100 usw. ist in diesem Fall eleganter und gültig als ein 000000, 001, 000100 usw. usw. Etc.

Hier ist der Code:

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

            // Using @Zac's initial solution
            String lastVal = dest.toString().substring(0, dstart) + dest.toString().substring(dend);
            String newVal = lastVal.substring(0, dstart) + source.toString() + lastVal.substring(dstart);
            int input = Integer.parseInt(newVal);

            // To avoid deleting all numbers and avoid @Guerneen4's case
            if (input < min && lastVal.equals("")) return String.valueOf(min);

            // Normal min, max check
            if (isInRange(min, max, input)) {

                // To avoid more than two leading zeros to the left
                String lastDest = dest.toString();
                String checkStr = lastDest.replaceFirst("^0+(?!$)", "");
                if (checkStr.length() < lastDest.length()) return "";

                return null;
            }
        } catch (NumberFormatException ignored) {}
        return "";
    }

Einen schönen Tag noch!

nnyerges
quelle
-1

Hier ist meine Sicht auf Pratik Sharmas Antwort für Kotlinund Doublewenn jemand sie braucht

class InputFilterMinMax : InputFilter {

private var min: Double = MIN_LIMIT
private var max: Double = MIN_LIMIT

constructor(min: Int, max: Int) {
    this.min = min.toDouble()
    this.max = max.toDouble()
}

constructor(min: String, max: String) {
    this.min = min.toDouble()
    this.max = max.toDouble()
}

constructor(min: Double, max: Double) {
    this.min = min
    this.max = max
}

override fun filter(
    source: CharSequence,
    start: Int,
    end: Int,
    dest: Spanned,
    dstart: Int,
    dend: Int
): CharSequence? {
    try {
        val input = (dest.toString() + source.toString()).toDouble()
        if (isInRange(min, max, input))
            return null
    } catch (nfe: NumberFormatException) {
        Timber.e(nfe)
    }

    return ""
}

private fun isInRange(a: Double, b: Double, c: Double): Boolean {
    return if (b > a) c in a..b else c in b..a
}
}
Varun Barve
quelle
Dieser Eingabefilter ist falsch, er ignoriert die Start-, End-, Start- und Endindizes des Textes. Wenn Sie also den Bearbeitungstext durch Einfügen eines Zeichens in die Mitte ändern, funktioniert er nicht richtig
Radu