¿Hay alguna manera de definir un valor mínimo y máximo para EditText en Android?

133

Quiero definir un valor mínimo y máximo para un EditText.

Por ejemplo: si alguna persona intenta ingresar un valor de mes en él, el valor debe estar entre 1-12.

Puedo hacerlo usando TextWatcherpero quiero saber si hay alguna otra forma de hacerlo en el archivo de diseño o en otro lugar.

Editar: no quiero limitar el recuento de caracteres. Quiero limitar el valor Por ejemplo, si limito los EditTextcaracteres del mes w cuando ingreso 12, lo aceptará, pero si ingreso 22 no debe aceptarlo mientras estoy ingresando.

mertaydin
fuente
Alguien debe hacer una biblioteca / colección de todos estos tipos de filtros de entrada. Entonces todos pueden trabajar y probarlos juntos. En lugar de que cada persona haga lo suyo.
Zapnologica
Use este filtro de edición de texto para resolver su problema. filter
Taras Smakula

Respuestas:

286

Primero haz esta clase:

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

Luego use esto de su Actividad:

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

Esto permitirá al usuario ingresar valores del 1 al 12 solamente .

EDITAR:

Establezca su texto de edición con android:inputType="number".

Puede encontrar más detalles en https://www.techcompose.com/how-to-set-minimum-and-maximum-value-in-edittext-in-android-app-development/ .

Gracias.

Pratik Sharma
fuente
1
@mertaydin seguro. pruébalo y avísame si necesitas mi ayuda. Gracias.
Pratik Sharma
12
Aah, necesito ayuda. Tengo un problema al escribir valor entre 1930 y 1999. Cuando escribo 1 está controlando el valor y 1 no está entre 1930 y 1999, por lo que no lo acepta.
mertaydin
1
@mertaydin Hola, lo siento, pero me encendí un poco ocupado con mi trabajo. Acabo de tener tiempo para analizar esto, creo que necesito hacer modificaciones en el algoritmo aplicado en la clase de filtro. Te actualizaré una vez que termine con eso.
Pratik Sharma
1
Algunos caracteres de sourcereemplazarán algunos caracteres en dest. Creo que debe simular el reemplazo y obtener el resultado final, luego validarlo.
SD
3
@Pratik Sharma, esto no funciona cuando entro en el rango de 1900 a 2000, ¿puede sugerir algo?
EminenT
89

Hay un pequeño error en el código de Pratik. Por ejemplo, si un valor es 10 y agrega un 1 al principio para hacer 110, la función de filtro tratará el nuevo valor como 101.

Vea a continuación una solución a esto:

@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
fuente
¡Gracias, esto me ayudó mucho!
joschplusa
44
Creo que esto es más claro en mi humilde opinión :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. Esta solución es más correcta de lo aceptado. Para verificarlo, por ejemplo, intente usar InputFilterMinMax con la opción selectAllOnFocus habilitada y compare el resultado.
Sash0k
1
Por qué no String newVal= dest.toString().substring(0, dstart) + source.toString().substring(start, end) + dest.toString().substring(dend, dest.toString().length());, se ve más limpio y claro.
Shishir Gupta
55
Como mencionó OP @mertaydin en un comentario sobre la respuesta de @Patrick, esta solución todavía tiene un defecto importante, me pregunto por qué no se ha informado: si min==3es imposible escribir cualquier número que comience con 1 o 2 (ej .: 15, 23)
Guerneen4
10

De lo que he visto de la solución de @ Patrik y la adición de @ Zac, el código provisto todavía tiene un gran problema:

Si min==3es imposible escribir cualquier número que comience con 1 o 2 (ej .: 15, 23)
Si min>=10es imposible escribir algo, ya que cada número tendrá que comenzar con 1,2,3 ...

Según tengo entendido, no podemos lograr la limitación min-max del EditTextvalor de an con el simple uso de la clase InputFilterMinMax, al menos no para el valor min, porque cuando el usuario escribe un número positivo, el valor aumenta y podemos realizar fácilmente un prueba sobre la marcha para verificar si ha alcanzado el límite o si se salió del rango y bloquea las entradas que no cumplen. Probar el valor mínimo es una historia diferente, ya que no podemos estar seguros de si el usuario ha terminado de escribir o no y, por lo tanto, no podemos decidir si debemos bloquear o no.

No es exactamente lo que OP solicitó, pero para fines de validación, combiné en mi solución una InputFilterpara probar los valores máximos, con una OnFocusChangeListenernueva prueba para el valor mínimo cuando EditTextpierde el foco asumiendo que el usuario terminó de escribir y es algo así:

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

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

        }
    }
}
}

A continuación, en la Actividad establecer el InputFilterMaxy el OnFocusChangeListenerMina EditText Nota: Puede 2 min y tanto en el máximo onFocusChangeListener.

mQteEditText.setOnFocusChangeListener( new OnFocusChangeListenerMin('20');
mQteEditText.setFilters(new InputFilter[]{new InputFilterMax(getActivity(),'50')});
Guerneen4
fuente
OnFocusChangeListenerMin no funciona, pone todos los valores desde cero
EminenT
1
¿Te importaría detallar un poco más? ¿Qué quieres decir con poner todos los valores de cero ?
Guerneen4
del código OnFocusChangeListenerMin debe estar funcionando por encima de 20 como se discutió en el problema, pero acepta todos los valores menores que 20 como 0, 1, 2, ------ 19, etc.
EminenT
¿encontraste alguna solución?
EminenT
He usado OnFoncusChangeListener con el propósito de validar, en mi caso muestro un error en EditText, notifico al usuario por un Toast que el valor no es bueno e invito a que ingrese un nuevo valor if(Integer.valueOf(val)<min){ //Notify user that the value is not good } . Puede hacer lo que quiera allí, notificar al usuario y configure EditText en blanco, no sé si esto responde a su pregunta
Guerneen4
9

Extensión de la respuesta de Pratik y Zac. Zac arregló un pequeño error de Pratik en su respuesta. Pero noté que el código no admite valores negativos, arrojará una excepción NumberFormatException. Para arreglar eso y permitir que el MIN sea negativo, use el siguiente código.

Agregue esta línea (en negrita) entre las otras dos líneas:

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

if (newVal.equalsIgnoreCase ("-") && min <0) devuelve nulo;

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
fuente
5

Si necesita un rango con números negativos como -90: 90, puede usar esta solución.

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
fuente
5

Extendí el código @Pratik Sharmas para usar objetos BigDecimal en lugar de ints para que pueda aceptar números más grandes y tener en cuenta cualquier formato en EditText que no sea un número (como el formato de moneda, es decir, espacios, comas y puntos)

EDITAR: tenga en cuenta que esta implementación tiene 2 como las cifras mínimas significativas establecidas en BigDecimal (vea la constante MIN_SIG_FIG) como la usé para la moneda, por lo que siempre había 2 números iniciales antes del punto decimal. Modifique la constante MIN_SIG_FIG según sea necesario para su propia implementación.

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
fuente
4

Encontré mi propia respuesta. Es muy tarde ahora pero quiero compartirlo contigo. Implemento esta interfaz:

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

}

Y luego impleméntalo de esta manera dentro de tu actividad:

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

Esta es una respuesta muy simple, si es mejor, dígame.

Nash Makineta
fuente
int n = 0; Es redundante. Dado que el valor predeterminado de n es 0.
Kenny Dabiri
1
¿Por qué int n = 0 es redundante aquí? es una variable local y no una variable de instancia aquí.
Usuario12111111
4

Hay algo mal en la respuesta aceptada.

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

Si muevo el cursor al centro del texto, luego escribo algo, entonces la declaración anterior producirá un resultado incorrecto. Por ejemplo, escriba "12" primero, luego escriba "0" entre 1 y 2, luego la declaración mencionada anteriormente producirá "120" en lugar de 102. Modifiqué esta declaración a las siguientes declaraciones:

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

Kotlin si alguien lo necesita (Use Utilities)

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

Luego usa esto de tu clase de Kotlin

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

Este EditText permite de 1 a 100.

Luego usa esto desde tu XML

android:inputType="number"
Alish
fuente
Uso la fuente de retorno y trabajo para mí ==> if (isInRange (min, max, input)) fuente de retorno
Muzafferus
3

Hice una forma más simple de establecer un mínimo / máximo en un Edittext. Uso el teclado aritmético y trabajo con este método:

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

El método acepta todos sus valores, pero si un valor de usuarios no cumple con sus límites, se establecerá automáticamente en el límite mínimo / máximo. Por ej. limit limin = 10, limax = 80 si el usuario establece 8, automáticamente 10 se guarda en una variable y EditText se establece en 10.

Argyris
fuente
3

Sé que ya hay un millón de respuestas a esto, con una aceptada. Sin embargo, hay numerosos errores en la respuesta aceptada y la mayoría del resto simplemente corrige uno (o tal vez dos) de ellos, sin expandirse a todos los casos de uso posibles.

Así que básicamente compilé la mayoría de las correcciones de errores sugeridas en las respuestas de soporte, así como agregué un método para permitir la entrada continua de números fuera del rango en la dirección de 0 (si el rango no comienza en 0), al menos hasta que sea seguro de que ya no puede estar en el rango. Para ser claros, este es el único momento que realmente causa problemas con muchas de las otras soluciones.

Aquí está la solución:

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

}

Tenga en cuenta que algunos casos de entrada son imposibles de manejar "activamente" (es decir, como el usuario lo está ingresando), por lo que debemos ignorarlos y manejarlos después de que el usuario haya terminado de editar el texto.

Así es como puede usarlo:

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

Ahora, cuando el usuario intenta escribir un número más cercano a 0 de lo que permite el rango, sucederá una de dos cosas:

  1. Si miny maxtienen el mismo número de dígitos, no se les permitirá ingresarlo una vez que lleguen al último dígito.

  2. Si se deja un número fuera del rango en el campo cuando el texto pierde el foco, se ajustará automáticamente al límite más cercano.

Y, por supuesto, al usuario nunca se le permitirá ingresar un valor más alejado de 0 que el rango permitido, ni es posible que un número como ese esté "accidentalmente" en el campo de texto por este motivo.

¿Problemas conocidos?)

  1. Esto solo funciona si EditTextpierde el foco cuando el usuario termina con él.

La otra opción es desinfectar cuando el usuario presiona la tecla "listo" / regresar, pero en muchos o incluso en la mayoría de los casos, esto causa una pérdida de enfoque de todos modos.

Sin embargo, cerrar el teclado virtual no desenfocará automáticamente el elemento. Estoy seguro de que el 99.99% de los desarrolladores de Android desearían que lo hiciera (y que el manejo del enfoque en los EditTextelementos fue menos problemático en general), pero hasta el momento no hay una funcionalidad incorporada para ello. El método más fácil que he encontrado para solucionar esto, si es necesario, es extender EditTextalgo como esto:

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

Esto "engañará" al filtro para que desinfecte la entrada aunque la vista no haya perdido el foco. Si la vista luego pierde el foco por sí misma, el saneamiento de entrada se activará nuevamente, pero nada cambiará ya que ya se solucionó.

Clausura

Uf. Eso fue mucho. Lo que originalmente parecía ser un problema bastante trivialmente fácil, terminó descubriendo muchas pequeñas piezas feas de Android de vainilla (al menos en Java). Y una vez más, solo necesita agregar el oyente y extenderlo EditTextsi su rango no incluye 0 de alguna manera. (Y de manera realista, si su rango no incluye 0 pero comienza en 1 o -1, tampoco tendrá problemas).

Como última nota, esto solo funciona para ints . Ciertamente, hay una manera de implementarlo para que funcione con decimales ( double, float), pero como ni yo ni el autor de la pregunta original lo necesitamos, no quiero profundizar en ello. Sería muy fácil usar simplemente el filtrado posterior a la finalización junto con las siguientes líneas:

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

Solo tendría que cambiar de inta float(o double), permitir la inserción de un solo .(o ,, ¿según el país?), Y analizar como uno de los tipos decimales en lugar de an int.

De todos modos, maneja la mayor parte del trabajo, por lo que funcionaría de manera muy similar.

VerumCH
fuente
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
fuente
2

Ejemplo muy simple en Kotlin:

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

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

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

por favor revise este código

    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 
  }

Use el siguiente enlace para obtener más detalles sobre edittext y los edittextfilteres con text watcher.

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

itsrajesh4uguys
fuente
OP quiere validarlo cuando se ingresa el valor. Creo que ha proporcionado una solución para el escenario después de ingresar el valor
MysticMagicϡ
No soy el interrogador. Tenía dudas sobre su respuesta, así que la estaba aclarando.
MysticMagicϡ
No quiero verificar el recuento de caracteres. Creo que está intentando verificar el recuento en este código: if (TextUtils.isEmpty (pass) || pass.length <[YOUR MIN LENGTH]) Solo limito el valor, por ejemplo, el valor del mes, el usuario debe escribir el valor entre 1-12 no 13,14, o etc. Entonces, 12,13,14, hasta que 99 tenga una longitud de 2 caracteres.
mertaydin
hola @mertaydin probaste con el enlace que te he proporcionado ... mira ese ejemplo ... puede ser eso lo que quieres. mirará el texto mientras
ingresas
Ok, gracias, probaré tu respuesta y la respuesta de @Pratik Sharma.
mertaydin
1

Si solo le preocupa el límite máximo, simplemente agregue la siguiente línea en

android:maxLength="10" 

Si necesita agregar un límite mínimo, puede hacerlo de esta manera, en este caso, el límite mínimo es 7. el usuario tiene restricciones para ingresar caracteres entre el límite mínimo y máximo (entre 8 y 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();
        }
    }

Si también necesita restringir al usuario para que ingrese 01 al inicio, modifique si la condición de esta manera

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

Al final, llame al método como

   ....else if (!(Helper.isValidMobilePhone(textMobileNo))){
                        Helper.setEditTextError(etMobileNo,"Invalid Mobile Number");
                    }......
Faakhir
fuente
2
Eso no es vlaue, eso es largo
portfoliobuilder
1

@Pratik Sharma

Para admitir números negativos , agregue el siguiente código dentro del método de filtro :

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

}

Luego use esto de su Actividad:

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

Establezca su texto de edición con:

android:inputType="number|numberSigned"
gadolf
fuente
0

// todavía tiene algún problema, pero aquí puede usar min, max en cualquier rango (positivo o negativo)

// 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
fuente
0

Para agregar a la respuesta de Pratik, aquí hay una versión modificada donde el usuario puede ingresar un mínimo de 2 dígitos también, por ejemplo, de 15 a 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;
    }}

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

Espero que esto ayude. amablemente no desestime sin razones.

sanjeeb
fuente
0

esta es la forma en que lo he usado, funciona para un número negativo

Primero, cree la clase MinMaxFIlter.java con el siguiente código:

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

Luego, cree y configure su filtro para su texto de edición de esta manera:

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
fuente
0

este es mi código max = 100, min = 0

xml

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

Java

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

        }

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

        @Override
        public void afterTextChanged(Editable editable) {

        }
    });
Hoàng
fuente
0

Puede hacer esto con un InputFilter. Aparentemente, solo puede usar esta interfaz de filtro de entrada. Antes de hacerlo de la manera molesta y crear una nueva clase que amplíe el filtro de entrada, puede usar este acceso directo con una instancia de interfaz de clase interna.

Por lo tanto solo haces esto:

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+"";

                    }
                }
        });

En este ejemplo, verifico si el valor de EditText es mayor que 8. De lo contrario, se establecerá en 8. Aparentemente, debe calcular el mínimo máximo o cualquier lógica de filtro por sí mismo. Pero al menos puedes escribir la lógica del filtro de forma bastante clara y corta directamente en EditText.

Espero que esto ayude

Christopher-Robin Fey Feysenbe
fuente
0

Para definir el valor mínimo de EditText, utilicé esto:

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

El código de @ Patrik tiene una buena idea pero con muchos errores. @Zac y @Anthony B (soluciones de números negativos) han resuelto algunos de ellos, pero el código de @ Zac todavía tiene 3 errores principales:

1. Si el usuario elimina todas las entradas en EditText, es imposible volver a escribir cualquier número. Por supuesto, esto puede controlarse utilizando un oyente modificado EditText en cada campo, pero borrará la belleza de usar una clase InputFilter común para cada EditText en tu aplicación.

2. Has @ Guernee4 dice que si, por ejemplo, min = 3, es imposible escribir cualquier número que comience con 1.

3. Si, por ejemplo, min = 0, puede escribir tiene muchos ceros que desee, que el resultado no es elegante. O también, si no importa cuál sea el valor mínimo, el usuario puede colocar el cursor en el tamaño izquierdo del primer número, un lugar con un montón de ceros a la izquierda, que tampoco es elegante.

Salí con estos pequeños cambios del código de @ Zac para resolver estos 3 errores. Con respecto al error # 3, todavía no he podido eliminar por completo todos los ceros a la izquierda; Siempre puede ser uno, pero un 00, 01, 0100, etc. en ese caso, es más elegante y válido que un 000000, 001, 000100, etc.etc. Etc.

Aquí está el código:

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

¡Que tengas un buen día!

nnyerges
fuente
-1

Aquí está mi opinión sobre la respuesta de Pratik Sharma Kotliny Doublesi alguien la necesita

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
fuente
Este filtro de entrada es incorrecto, ignora los índices de inicio, finalización, inicio, finalización del texto, por lo que si cambia el texto de edición insertando un carácter en el medio, no funcionará correctamente
Radu