Chcę zdefiniować wartość minimalną i maksymalną dla pliku EditText
.
Na przykład: jeśli jakakolwiek osoba próbuje wprowadzić w nim wartość miesiąca, wartość musi mieścić się w przedziale 1-12.
Mogę to zrobić za pomocą, TextWatcher
ale chcę wiedzieć, czy istnieje inny sposób, aby to zrobić w pliku układu lub w innym miejscu.
Edycja: nie chcę ograniczać liczby znaków. Chcę ograniczyć wartość. Na przykład, jeśli ograniczę EditText
liczbę znaków w miesiącu, kiedy wprowadzę 12, to zaakceptuje to, ale jeśli wprowadzę 22, nie może tego zaakceptować podczas wprowadzania.
android
android-edittext
mertaydin
źródło
źródło
Odpowiedzi:
Najpierw zrób tę klasę:
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; } }
Następnie użyj tego ze swojej aktywności:
EditText et = (EditText) findViewById(R.id.myEditText); et.setFilters(new InputFilter[]{ new InputFilterMinMax("1", "12")});
Pozwoli to użytkownikowi wprowadzić tylko wartości od 1 do 12 .
EDYTOWAĆ :
Ustaw swój edittext za pomocą
android:inputType="number"
.Więcej szczegółów można znaleźć na https://www.techcompose.com/how-to-set-minimum-and-maximum-value-in-edittext-in-android-app-development/ .
Dzięki.
źródło
source
zastąpią niektóre znaki wdest
. Myślę, że powinieneś zasymulować wymianę i uzyskać wynik końcowy, a następnie zweryfikować go.W kodzie Pratik jest mały błąd. Na przykład, jeśli wartość wynosi 10 i dodasz 1 na początku, aby uzyskać 110, funkcja filtru potraktuje nową wartość jako 101.
Poniżej znajdziesz rozwiązanie tego problemu:
@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 ""; }
źródło
String replacement = source.subSequence(start, end).toString(); String newVal = dest.subSequence(0, dstart).toString() + replacement + dest.subSequence(dend, dest.length()).toString();
String newVal= dest.toString().substring(0, dstart) + source.toString().substring(start, end) + dest.toString().substring(dend, dest.toString().length());
, wygląda bardziej czysto i wyraźnie.min==3
wtedy nie można wpisać żadnej liczby zaczynającej się od 1 lub 2 (np: 15, 23)Z tego, co widziałem w rozwiązaniu @ Patrik i dodatku @ Zaca, dostarczony kod nadal ma duży problem:
Jeśli
min==3
wtedy nie można wpisać żadnej liczby zaczynającej się od 1 lub 2 (np .: 15, 23)Jeśli
min>=10
wtedy nie można nic wpisać, ponieważ każda liczba będzie musiała zaczynać się od 1, 2, 3 ...W moim rozumieniu nie możemy osiągnąć ograniczenia min-max wartości an
EditText
'przy prostym użyciu klasyInputFilterMinMax
, przynajmniej nie dla wartości min, ponieważ kiedy użytkownik wpisuje liczbę dodatnią, wartość rośnie i możemy łatwo wykonać test w locie, aby sprawdzić, czy osiągnął limit lub przekroczył zakres i zablokować wpisy, które nie są zgodne. Testowanie wartości min to inna historia, ponieważ nie możemy być pewni, czy użytkownik skończył pisać, czy nie, i dlatego nie możemy zdecydować, czy powinniśmy blokować, czy nie.Nie jest to dokładnie to, o co prosił OP, ale dla celów walidacji połączyłem w moim rozwiązaniu i
InputFilter
przetestowałem wartości maksymalne, zOnFocusChangeListener
ponownym przetestowaniem wartości minimalnej, gdyEditText
traci fokus, zakładając, że użytkownik skończył pisać i wygląda to mniej więcej tak: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 ""; } }
I
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 } } } } }
Następnie w Aktywności ustaw
InputFilterMax
i,OnFocusChangeListenerMin
abyEditText
zauważyć: Możesz 2 min i maxonFocusChangeListener
.mQteEditText.setOnFocusChangeListener( new OnFocusChangeListenerMin('20'); mQteEditText.setFilters(new InputFilter[]{new InputFilterMax(getActivity(),'50')});
źródło
if(Integer.valueOf(val)<min){ //Notify user that the value is not good }
Możesz tam robić, co chcesz, powiadom user i ustaw EditText na puste, nie wiem, czy to odpowiada na twoje pytanieRozszerzenie odpowiedzi Pratika i Zaca. Zac naprawił mały błąd Pratika w swojej odpowiedzi. Ale zauważyłem, że kod nie obsługuje wartości ujemnych, wyrzuci wyjątek NumberFormatException. Aby to naprawić i pozwolić MIN na wartość ujemną, użyj następującego kodu.
Dodaj tę linię (pogrubioną czcionką) między pozostałymi dwoma wierszami:
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 ""; }
źródło
Kotlin, jeśli ktoś tego potrzebuje (użyj narzędzi)
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 } }
Następnie użyj tego z klasy Kotlin
percentage_edit_text.filters = arrayOf(Utilities.InputFilterMinMax(1, 100))
Ten EditText dopuszcza od 1 do 100.
Następnie użyj tego z pliku XML
android:inputType="number"
źródło
Jeśli potrzebujesz zakresu z liczbami ujemnymi, takimi jak -90: 90, możesz użyć tego rozwiązania.
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; } }
źródło
Rozszerzyłem kod @Pratik Sharmas, aby używać obiektów BigDecimal zamiast ints, aby mógł akceptować większe liczby i uwzględniać dowolne formatowanie w EditText, które nie jest liczbą (jak formatowanie waluty, tj. Spacje, przecinki i kropki)
EDYCJA: zauważ, że ta implementacja ma 2 jako minimalne cyfry znaczące ustawione na BigDecimal (patrz stała MIN_SIG_FIG), ponieważ użyłem jej do waluty, więc zawsze były 2 liczby wiodące przed przecinkiem. Zmień stałą MIN_SIG_FIG, jeśli jest to konieczne dla własnej implementacji.
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; }
źródło
Znalazłem własną odpowiedź. Jest już bardzo późno, ale chcę się z wami tym podzielić. Implementuję ten interfejs:
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; } }
A następnie zaimplementuj to w ten sposób w swojej działalności:
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(); } } }); }
To bardzo prosta odpowiedź, a jeśli lepiej, powiedz mi.
źródło
W zaakceptowanej odpowiedzi jest coś nie tak.
int input = Integer.parseInt(dest.toString() + source.toString());
Jeśli przesunę kursor na środek tekstu, a następnie coś wpiszę, to powyższe stwierdzenie da błędny wynik. Na przykład najpierw wpisz „12”, a następnie wpisz „0” między 1 a 2, wtedy powyższa instrukcja wyświetli „120” zamiast 102. Zmodyfikowałem to oświadczenie na poniższe:
String destString = dest.toString(); String inputString = destString.substring(0, dstart) + source.toString() + destString.substring(dstart); int input = Integer.parseInt(inputString);
źródło
Zrobiłem prostszy sposób, aby ustawić min / max na Edittext. Używam klawiatury arytmetycznej i pracuję tą metodą:
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()); } }
Metoda akceptuje wszystkie Twoje wartości, ale jeśli wartość użytkowników nie jest zgodna z Twoimi limitami, zostanie automatycznie ustawiona na limit min / max. Na przykład. limit limin = 10, limax = 80, jeśli użytkownik ustawi 8, automatycznie 10 zostanie zapisane w zmiennej, a EditText zostanie ustawiony na 10.
źródło
Wiem, że jest już milion odpowiedzi na to pytanie, z których jedna została zaakceptowana. Jednak w zaakceptowanej odpowiedzi jest wiele błędów, a większość pozostałych po prostu naprawia jeden (lub może dwa) z nich, bez rozszerzania na wszystkie możliwe przypadki użycia.
Więc w zasadzie skompilowałem większość poprawek błędów sugerowanych w odpowiedziach wsparcia, a także dodałem metodę umożliwiającą ciągłe wprowadzanie liczb spoza zakresu w kierunku 0 (jeśli zakres nie zaczyna się od 0), przynajmniej do momentu pewny, że nie może już znajdować się w zasięgu. Aby było jasne, jest to jedyny przypadek, który naprawdę powoduje problemy z wieloma innymi rozwiązaniami.
Oto poprawka:
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(""); } } }
Zauważ, że niektóre przypadki wprowadzania danych są niemożliwe do obsłużenia "aktywnie" (tj. Gdy użytkownik je wprowadza), więc musimy je zignorować i zająć się nimi po zakończeniu edycji tekstu przez użytkownika.
Oto, jak możesz tego użyć:
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);
Teraz, gdy użytkownik spróbuje wpisać liczbę bliższą 0 niż pozwala zakres, nastąpi jedna z dwóch rzeczy:
Jeśli
min
imax
mają taką samą liczbę cyfr, nie będą mogli w ogóle jej wprowadzić, gdy dojdą do ostatniej cyfry.Jeśli liczba spoza zakresu pozostanie w polu, gdy tekst straci ostrość, zostanie automatycznie dopasowany do najbliższej granicy.
Oczywiście, użytkownik nigdy nie będzie mógł wprowadzić wartości większej od 0, niż pozwala na to zakres, ani też nie jest możliwe, aby taka liczba „przypadkowo” znalazła się w polu tekstowym z tego powodu.
Znane problemy?)
EditText
straci fokus, gdy użytkownik skończy z nim.Inną opcją jest odkażanie, gdy użytkownik naciśnie klawisz „done” / Return, ale w wielu lub nawet większości przypadków powoduje to utratę koncentracji.
Jednak zamknięcie miękkiej klawiatury nie spowoduje automatycznego usunięcia fokusu elementu. Jestem pewien, że 99,99% programistów Androida by tego życzyło (a skupienie się na
EditText
elementach było ogólnie mniejszym grzęzawiskiem), ale jak dotąd nie ma wbudowanej funkcjonalności. Najłatwiejszą metodą obejścia tego problemu, jeśli zajdzie taka potrzeba, jest rozszerzenieEditText
czegoś takiego: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); } }
Spowoduje to „oszukanie” filtru w celu oczyszczenia wejścia, nawet jeśli widok w rzeczywistości nie stracił ostrości. Jeśli zdarzy się, że widok sam się straci skupienie, ponownie uruchomi się sanacja wejściowa, ale nic się nie zmieni, ponieważ zostało już naprawione.
Zamknięcie
Uff. To było dużo. To, co początkowo wydawało się być dość banalnie łatwym problemem, zakończyło się odkryciem wielu małych brzydkich kawałków waniliowego Androida (przynajmniej w Javie). I jeszcze raz musisz tylko dodać odbiornik i rozszerzyć zakres,
EditText
jeśli twój zakres nie zawiera w jakiś sposób 0. (I realistycznie, jeśli twój zakres nie obejmuje 0, ale zaczyna się od 1 lub -1, również nie napotkasz problemów).Na koniec uwaga, to działa tylko dla int . Z pewnością jest sposób na zaimplementowanie go do pracy z liczbami dziesiętnymi (
double
,float
), ale ponieważ ani ja, ani pierwotny pytający nie potrzebujemy tego, nie chcę szczególnie zagłębiać się w to wszystko. Byłoby bardzo łatwo po prostu użyć filtrowania po ukończeniu wraz z następującymi wierszami:// 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;
Musiałbyś tylko zmienić z
int
nafloat
(lubdouble
), zezwolić na wstawienie pojedynczego.
(lub,
, w zależności od kraju?) I przeanalizować jako jeden z typów dziesiętnych zamiastint
.To i tak obsługuje większość pracy, więc działałoby bardzo podobnie.
źródło
@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; }
źródło
Bardzo prosty przykład na Kotlinie:
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) { "" } }
źródło
proszę sprawdzić ten kod
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 }
Skorzystaj z poniższego łącza, aby uzyskać więcej informacji o edittext i edittextfilteres z przeglądarką tekstu.
http://www.mobisoftinfotech.com/blog/android/android-edittext-setfilters-example-numeric-text-field-patterns-and-length-restriction/
źródło
Jeśli martwisz się tylko maksymalnym limitem, po prostu dodaj poniższą linię
android:maxLength="10"
Jeśli chcesz dodać minimalny limit, możesz to zrobić w ten sposób, w tym przypadku minimalny limit to 7. użytkownik jest ograniczony do wprowadzania znaków między minimalnym a maksymalnym limitem (między 8 a 10)
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(); } }
Jeśli chcesz również ograniczyć użytkownika do wprowadzania 01 na początku, zmodyfikuj warunek w ten sposób
if (!(number.startsWith("01")) || number.length() < 8 || number.length() >10 ) { . . . }
Na koniec wywołanie metody takiej jak
....else if (!(Helper.isValidMobilePhone(textMobileNo))){ Helper.setEditTextError(etMobileNo,"Invalid Mobile Number"); }......
źródło
@Pratik Sharma
Aby obsługiwać liczby ujemne , dodaj następujący kod w metodzie filtru :
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; } }
Następnie użyj tego ze swojej aktywności:
findViewById(R.id.myEditText).setFilters(new InputFilter[]{ new InputFilterMinMax(1, 12)});
Ustaw swój edittext za pomocą:
android:inputType="number|numberSigned"
źródło
Kod @ Patrik ma fajny pomysł, ale zawiera wiele błędów. @Zac i @Anthony B (rozwiązania liczb ujemnych) rozwiązały niektóre z nich, ale kod @ Zaca nadal zawiera 3 główne błędy:
1. Jeśli użytkownik usunie wszystkie wpisy w EditText, nie będzie można ponownie wpisać żadnej liczby. Oczywiście można to kontrolować za pomocą odbiornika ze zmianą EditText w każdym polu, ale usunie to piękno używania wspólnej klasy InputFilter dla każdego pola EditText w swojej aplikacji.
2. Czy @ Guernee4 mówi, że jeśli na przykład min = 3, nie można wpisać żadnej liczby zaczynającej się od 1.
3. Jeśli na przykład min = 0, możesz wpisać wiele zer, które chcesz, że nie jest to elegancki wynik. Lub też, jeśli nie ważne jaka jest wartość min, użytkownik może umieścić kursor w lewym rozmiarze pierwszej liczby, umieszczając kilka wiodących zer po lewej, również nie eleganckie.
Wymyśliłem te małe zmiany w kodzie @ Zaca, aby rozwiązać te 3 błędy. Jeśli chodzi o błąd nr 3, nadal nie byłem w stanie całkowicie usunąć wszystkich wiodących zer po lewej stronie; Zawsze może to być jeden, ale w tym przypadku 00, 01, 0100 itp. Jest bardziej elegancki i ważny niż 000000, 001, 000100 itd. Itd. Itp.
Oto kod:
@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 ""; }
Miłego dnia!
źródło
// nadal ma jakiś problem, ale tutaj możesz użyć min, max w dowolnym zakresie (dodatnim lub ujemnym)
// 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 ... } } } });
źródło
Aby dodać do odpowiedzi Pratik, oto zmodyfikowana wersja, w której użytkownik może również wprowadzić min 2 cyfry, na przykład 15 do 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; }}
Mam nadzieję że to pomoże. uprzejmie nie głosuj przeciwnie bez powodu.
źródło
oto sposób, w jaki użyłem, działa dla liczby ujemnej
Najpierw utwórz klasę MinMaxFIlter.java z następującym kodem:
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; } } }
Następnie utwórz i ustaw filtr na swój edittext w następujący sposób:
EditText edittext = new EditText(context); editext.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED); eInt.setFilters(new InputFilter[]{new MinMaxFilter(min, max)});
źródło
to jest mój kod 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" />
Jawa
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) { } });
źródło
Możesz to zrobić za pomocą filtra InputFilter. Najwyraźniej jest tylko ten interfejs filtra wejściowego, którego możesz użyć. Zanim zrobisz to w irytujący sposób, aby utworzyć nową klasę, która rozszerza filtr wejściowy, możesz użyć tego skrótu z instancją interfejsu innerclass.
Dlatego po prostu zrób to:
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+""; } } });
W tym przykładzie sprawdzam, czy wartość EditText jest większa niż 8. Jeśli nie, powinna być ustawiona na 8. Tak więc obecnie musisz samodzielnie obliczyć min max lub jakąkolwiek logikę filtra. Ale przynajmniej możesz napisać logikę filtru całkiem schludną i krótką bezpośrednio w EditText.
Mam nadzieję że to pomoże
źródło
Aby zdefiniować minimalną wartość EditText, użyłem tego:
if (message.trim().length() >= 1 && message.trim().length() <= 12) { // do stuf } else { // Too short or too long }
źródło
Natknąłem się na ten problem, kiedy tworzyłem projekt dla zwierząt domowych. Przeczytałem tutaj niektóre odpowiedzi i prawdopodobnie zaadoptowałem w moim kodzie jedną lub dwie z nich.
ZŁA WIADOMOŚĆ: Udało mi się to zrobić bardzo brudnym sposobem (zobaczysz dlaczego). Wciąż jest kilka błędów, których nie chciałem rozwiązać (pisałem o drugiej w nocy), na przykład jeśli
min
wartość wynosi 10, nie będziesz w stanie wprowadzić liczby na początek.DOBRA WIADOMOŚĆ: Udało mi się pozbyć błędu z zerami wiodącymi, o którym wspominał @nnyerges, używając wyłącznie
InputFilter
do tylko jednego 0, czyli jeślimin
wartość wynosi 0. Jednak limit mojej implementacjiInputFilter
przychodzi, gdy użytkownik usuwa pierwsza liczba (y), po której następuje zero (y), np. jeśli na początku użytkownik wprowadzi dane,1000
ale potem usunie1
, to stanie się000
. To jest brzydkie i właśnie tam pojawia się moje brudne brzydkie użycieTextChangedListener
/TextWatcher
. (Wiem, że OP powiedział już, że może to zrobić używającTextWatcher
, ale nieważne.)Kolejne ograniczenie (a może MOJE ograniczenie?) Używanie
InputFilter
jest, gdyinputType
jestnumberDecimal
, co oznacza użytkownik może wprowadzić separator dziesiętny. Przykładowy przypadek: zakres to0 - 100
dane wprowadzane przez użytkownika99.99
, użytkownik następnie usuwa separator, musielibyśmy również dostosować go do wartości ujemnej .9999
. Nie chcemy tego, prawda?Niektóre funkcje w moim kodzie, czy ci się to podoba, czy nie, obejmują obcinanie nieistotnych
0
s, np. Jeśli użytkownik usunie1
z10032
, o ile jest w zdefiniowanym zakresie, obcina początkowe0
s, więc ostateczny wynik wyniesie 32. Po drugie, gdy użytkownik spróbuje usunąć-
notację ujemną ( ) lub separator dziesiętny (.
), sprawdzi, czy wynikowa liczba po usunięciu jest nadal w zakresie. Jeśli nie, powróci do ostatniej wartości. Innymi słowy, użytkownik nie może zrobić tego rodzaju usunięcia. Ale , jeśli wolisz, aby ustawić nowe wartości do jednejmin
lubmax
wartości, gdy tak się stanie, można to zrobić, too.UWAGA: Jestem zbyt leniwy, by zawracać sobie głowę lokalizacją, więc osoby, które używają przecinka jako separatora dziesiętnego, będą musiały ręcznie to zmienić.
DRUGA UWAGA: Kod jest bardzo niechlujny i prawdopodobnie zawiera kilka lub wiele zbędnych kontroli, więc bądź świadomy. Ponadto, jeśli masz sugestie, nie krępuj się komentować, ponieważ ja też chcę to poprawić. Być może będę musiał go użyć w przyszłości. Kto wie?
W każdym razie, oto jest.
import android.text.InputFilter; import android.text.Spanned; import android.util.Log; public class InputFilterMinMax implements InputFilter { private double min, max; public InputFilterMinMax(double min, double max) { this.min = min; this.max = max; } public InputFilterMinMax(String min, String max) { this.min = Double.parseDouble(min); this.max = Double.parseDouble(max); } @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { try { String lastVal = dest.toString(); String newVal = lastVal.substring(0, dstart) + source.toString() + lastVal.substring(dstart); String strInput = source.toString(); double input; if (strInput.equals("-") && (lastVal.length() == 0 || lastVal.equals("0"))) { return null; } else { input = Double.parseDouble(newVal); } if (isInRange(min, max, input)) { try { if (lastVal.equals("0") && strInput.equals("0") && !strInput.equals(".")) { Log.d("Checkpoint 1", "Can't put 0 again."); return ""; } else if (strInput.equals("0")) { if (dstart == 0) { if (lastVal.substring(0, 1).equals("0")) { Log.d("Checkpoint 2", "Can't put 0 again."); return ""; } else if (!lastVal.substring(0, 1).equals(".")) { Log.d("Checkpoint 3", "Can't put 0 in front of them."); return ""; } } else { if (lastVal.substring(0, 1).equals("0") && dstart == 1) { Log.d("Checkpoint 4", "Can't put 0 again."); return ""; } else if (lastVal.substring(0, 1).equals("-")) { if (Double.parseDouble(lastVal) == 0) { if (!lastVal.contains(".")) { Log.d("Checkpoint 5", "Can't put 0 here."); return ""; } else { if (dstart <= lastVal.indexOf(".")) { Log.d("Checkpoint 6", "Can't put 0 here."); return ""; } } } else { if (lastVal.indexOf("0") == 1 && (dstart == 1 || dstart == 2)) { Log.d("Checkpoint 7", "Can't put 0 here."); return ""; } else if ((!lastVal.substring(1, 2).equals("0") && !lastVal.substring(1, 2).equals(".")) && dstart == 1) { Log.d("Checkpoint 8", "Can't put 0 here."); return ""; } } } } } /** * If last value is a negative that equals min value, * and user tries to input a decimal separator at the * very end, ignore it, because they won't be able to * input anything except 0 after that anyway. */ if (strInput.equals(".") && lastVal.substring(0,1).equals("-") && Double.parseDouble(lastVal) == min && dstart == lastVal.length()) { return ""; } } catch (Exception e) { } return null; } } catch (Exception ignored) { ignored.printStackTrace(); } return ""; } private boolean isInRange(double a, double b, double c) { return b > a ? c >= a && c <= b : c >= b && c <= a; } }
A teraz naprawdę brudna część:
import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.text.Editable; import android.text.InputFilter; import android.text.TextWatcher; import android.util.Log; import android.widget.EditText; public class MainActivity extends AppCompatActivity implements TextWatcher { private EditText editInput; /** * Var to store old value in case the new value is either * out of range or invalid somehow. This was because I * needed a double value for my app, which means I can * enter a dot (.), and that could mean trouble if I decided * to delete that dot, e.g. assume the range is 0 - 100. * At first I enter 99.99, the InputFilter would allow that, * but what if somewhere down the line I decided to delete * the dot/decimal separator for "fun"? * Wow, now I have 9999. * Also, when I delete negative notation, it can produce * the same problem. */ private String oldVal; private int min, max; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editInput = findViewById(R.id.edt_input); editInput.addTextChangedListener(this); min = -1600; max = 1500; editInput.setFilters(new InputFilter[]{new InputFilterMinMax(min, max)}); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { oldVal = saveOldValue(s, start); } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { validateChange(editInput, oldVal); } private String saveOldValue(CharSequence s, int start) { String oldVal = s.toString(); if (oldVal.contains(".") && start == oldVal.indexOf(".") && start != oldVal.length() - 1) { return oldVal; } else if (oldVal.contains("-") && start == oldVal.indexOf("-") && start != oldVal.length() - 1) { return oldVal; } return null; } private void validateChange(EditText editText, String oldVal) { String strNewVal = editText.getText().toString().trim(); boolean isChanged = false; if (strNewVal.indexOf("0") == 0 || (strNewVal.indexOf("-") == 0 && strNewVal.indexOf("0") == 1)) { if (strNewVal.contains(".")) { while ((strNewVal.indexOf("0") == 0 && strNewVal.indexOf(".") != 1 && strNewVal.length() > 2) || (strNewVal.indexOf("0") == 1 && strNewVal.indexOf(".") != 2 && strNewVal.length() > 3)) { Log.d("Trimming 0", ""); strNewVal = strNewVal.replaceFirst("0", ""); isChanged = true; } } else if (!strNewVal.contains(".")) { while (strNewVal.indexOf("0") == 0 && strNewVal.length() > 1) { Log.d("Trimming 0", ""); strNewVal = strNewVal.replaceFirst("0", ""); isChanged = true; } if (Double.parseDouble(strNewVal) > max) { editText.setText(oldVal); // Or, you can set it to max values here. return; } } } if (strNewVal.indexOf(".") == 0) { strNewVal = "0" + strNewVal; isChanged = true; } try { double newVal = Double.parseDouble(strNewVal); Log.d("NewVal: ", String.valueOf(newVal)); if (newVal > max || newVal < min) { Log.d("Over Limit", "Let's Reset"); editText.setText(oldVal); // Or, you can set it to min or max values here. } } catch (NumberFormatException e) { e.printStackTrace(); } if (isChanged) { editText.setText(strNewVal); } } }
źródło
Oto moje podejście do odpowiedzi Pratik Sharma
Kotlin
iDouble
jeśli ktoś jej potrzebujeclass 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 } }
źródło