Czy istnieje sposób na zdefiniowanie wartości minimalnej i maksymalnej dla EditText w systemie Android?

136

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ą, TextWatcherale 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ę EditTextliczbę znaków w miesiącu, kiedy wprowadzę 12, to zaakceptuje to, ale jeśli wprowadzę 22, nie może tego zaakceptować podczas wprowadzania.

mertaydin
źródło
Ktoś powinien stworzyć bibliotekę / zbiór wszystkich tych typów filtrów wejściowych. Wtedy każdy może wspólnie pracować i testować. Zamiast robić swoje.
Zapnologica
Użyj tego filtru edycji tekstu, aby rozwiązać problem. filtr
Taras Smakula

Odpowiedzi:

288

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.

Pratik Sharma
źródło
1
@mertaydin sure. spróbuj, a następnie daj mi znać, jeśli potrzebujesz mojej pomocy. Dzięki.
Pratik Sharma
12
Ach, potrzebuję pomocy. Mam problem z zapisywaniem wartości między 1930 a 1999. Kiedy piszę 1, kontroluje wartość, a 1 nie jest między 1930 a 1999, więc nie akceptuje tego.
mertaydin
1
@mertaydin Hej, przepraszam, ale zapaliłem się trochę zajęty pracą. Właśnie miałem trochę czasu, żeby się temu przyjrzeć, myślę, że muszę dokonać modyfikacji w algorytmie zastosowanym w klasie filtrów. Poinformuję cię, kiedy już to zrobię.
Pratik Sharma
1
Niektóre znaki z sourcezastąpią niektóre znaki w dest. Myślę, że powinieneś zasymulować wymianę i uzyskać wynik końcowy, a następnie zweryfikować go.
SD
3
@Pratik Sharma, To nie działa, gdy wpisuję zakres od 1900 do 2000, Czy możesz coś zasugerować
EminenT
90

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 "";
}
Zac
źródło
Dzięki, to bardzo mi pomogło!
joschplusa,
4
Myślę, że to jest jaśniejsze 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. to rozwiązanie bardziej poprawne niż przyjęte. Aby to sprawdzić np. Spróbuj użyć InputFilterMinMax z włączoną opcją selectAllOnFocus i porównaj wynik.
Sash0k
1
Dlaczego nie 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.
Shishir Gupta
5
Jak wspomniał OP @mertaydin w komentarzu do odpowiedzi @Patrick, to rozwiązanie wciąż ma poważną wadę, zastanawiam się, dlaczego nie zostało to zgłoszone: jeśli min==3wtedy nie można wpisać żadnej liczby zaczynającej się od 1 lub 2 (np: 15, 23)
Guerneen4
10

Z tego, co widziałem w rozwiązaniu @ Patrik i dodatku @ Zaca, dostarczony kod nadal ma duży problem:

Jeśli min==3wtedy nie można wpisać żadnej liczby zaczynającej się od 1 lub 2 (np .: 15, 23)
Jeśli min>=10wtedy 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 klasy InputFilterMinMax, 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 InputFilterprzetestowałem wartości maksymalne, z OnFocusChangeListenerponownym przetestowaniem wartości minimalnej, gdy EditTexttraci 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 InputFilterMaxi, OnFocusChangeListenerMinaby EditText zauważyć: Możesz 2 min i max onFocusChangeListener.

mQteEditText.setOnFocusChangeListener( new OnFocusChangeListenerMin('20');
mQteEditText.setFilters(new InputFilter[]{new InputFilterMax(getActivity(),'50')});
Guerneen4
źródło
OnFocusChangeListenerMin nie działa, umieszcza wszystkie wartości od zera
EminenT
1
Czy możesz podać więcej szczegółów? co masz na myśli umieścić wszystkie wartości od zera ?
Guerneen4
z kodu OnFocusChangeListenerMin musi działać powyżej 20, jak omówiono w problemie, ale akceptuje wszystkie wartości mniejsze niż 20, takie jak 0, 1, 2, ------ 19 itd.
EminenT
czy znalazłeś jakieś rozwiązanie?
EminenT
Użyłem OnFoncusChangeListener w celu walidacji, w moim przypadku wyświetlam błąd w EditText, powiadamiam użytkownika Toastem, że wartość nie jest dobra i zapraszam go do wprowadzenia nowej. 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 pytanie
Guerneen4
9

Rozszerzenie 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 "";
}
Anthony B.
źródło
6

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"
Alish
źródło
Używam źródła zwrotnego i pracuję dla mnie ==> if (isInRange (min, max, input)) return source
Muzafferus
5

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;
}
}
Denys Vasylenko
źródło
5

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;
}
AndroidNoob
źródło
4

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.

Nash Makineta
źródło
int n = 0; jest zbędny. Ponieważ domyślną wartością n jest 0.
Kenny Dabiri,
1
Dlaczego int n = 0 jest tutaj zbędne? jest to zmienna lokalna, a nie zmienna instancji.
User12111111,
4

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
3

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.

Argyris
źródło
3

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:

  1. Jeśli mini maxmają taką samą liczbę cyfr, nie będą mogli w ogóle jej wprowadzić, gdy dojdą do ostatniej cyfry.

  2. 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?)

  1. Działa to tylko wtedy, gdy EditTextstraci 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 EditTextelementach 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 rozszerzenie EditTextczegoś 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, EditTextjeś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 intna float(lub double), zezwolić na wstawienie pojedynczego .(lub ,, w zależności od kraju?) I przeanalizować jako jeden z typów dziesiętnych zamiast int.

To i tak obsługuje większość pracy, więc działałoby bardzo podobnie.

VerumCH
źródło
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
źródło
2

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) {
        ""
    }
}
Andrzej
źródło
1

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/

itsrajesh4uguys
źródło
OP chce sprawdzić poprawność podczas wprowadzania wartości. Myślę, że podałeś rozwiązanie scenariusza po wprowadzeniu wartości
MysticMagicϡ
Nie jestem pytającym. Miałem tylko wątpliwości co do twojej odpowiedzi, więc wyjaśniłem to.
MysticMagicϡ,
Nie chcę sprawdzać liczby znaków. Myślę, że próbujesz sprawdzić liczbę w tym kodzie: jeśli (TextUtils.isEmpty (pass) || pass.length <[YOUR MIN LENGTH]) Po prostu ograniczam wartość, na przykład wartość miesiąca, użytkownik musi wpisać wartość między 1-12, a nie 13,14, itd. Tak więc 12,13,14, aż 99 ma 2 znaki.
mertaydin
cześć @mertaydin, czy próbowałeś z linkiem, który ci podałem ... zobacz ten przykład ... może to jest to, czego chcesz. będzie oglądać tekst podczas wpisywania ..
itsrajesh4uguys
Ok dzięki, spróbuję Twojej odpowiedzi i odpowiedzi @Pratik Sharma.
mertaydin
1

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");
                    }......
Faakhir
źródło
2
To nie jest vlaue, to jest długość
portfoliobuilder
1

@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"
gadolf
źródło
1

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!

nnyerges
źródło
0

// 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 ...     
             }
         }
      }
 });
CHTsai
źródło
0

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

dodane: if (end == 1) min = Integer.parseInt (source.toString ());

Mam nadzieję że to pomoże. uprzejmie nie głosuj przeciwnie bez powodu.

sanjeeb
źródło
0

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)});
maloromano
źródło
0

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

        }
    });
Hoàng
źródło
0

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

Christopher-Robin Fey Feysenbe
źródło
0

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
}
Bonne Bogaert
źródło
0

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 minwartość 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 InputFilterdo tylko jednego 0, czyli jeśli minwartość wynosi 0. Jednak limit mojej implementacji InputFilterprzychodzi, gdy użytkownik usuwa pierwsza liczba (y), po której następuje zero (y), np. jeśli na początku użytkownik wprowadzi dane, 1000ale potem usunie 1, to stanie się 000. To jest brzydkie i właśnie tam pojawia się moje brudne brzydkie użycie TextChangedListener/ TextWatcher. (Wiem, że OP powiedział już, że może to zrobić używając TextWatcher, ale nieważne.)
Kolejne ograniczenie (a może MOJE ograniczenie?) Używanie InputFilterjest, gdy inputTypejest numberDecimal, 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 0s, np. Jeśli użytkownik usunie 1z 10032, o ile jest w zdefiniowanym zakresie, obcina początkowe 0s, 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 jednej minlub maxwartoś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);
        }
    }
}
LuckMan
źródło
-1

Oto moje podejście do odpowiedzi Pratik Sharma Kotlini Doublejeśli ktoś jej potrzebuje

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
źródło
Ten filtr wejściowy jest nieprawidłowy, ignoruje indeksy początku, końca, dstart, dend tekstu, więc jeśli zmienisz tekst edycji, wstawiając znak w środku, nie będzie działał poprawnie
Radu