Existe uma maneira de definir um valor mínimo e máximo para EditText no Android?

133

Eu quero definir um valor mínimo e máximo para um EditText.

Por exemplo: se alguém tentar inserir um valor mensal, o valor deverá estar entre 1 e 12.

Posso fazer isso usando, TextWatchermas quero saber se existe outra maneira de fazer isso no arquivo de layout ou em outro local.

Editar: não quero limitar a contagem de caracteres. Eu quero limitar o valor. Por exemplo, se eu limitar os EditTextcaracteres do mês w quando digitar 12, ele será aceito, mas se eu inserir 22, ele não deverá ser aceito enquanto eu estiver inserindo.

mertaydin
fonte
Alguém deve fazer uma biblioteca / coleção de todos esses tipos de filtros de entrada. Então todos podem trabalhar e testá-los juntos. Em vez de cada pessoa fazer suas próprias coisas.
Zapnologica
Use este filtro de edição de texto para resolver seu problema. filtro
Taras Smakula

Respostas:

286

Primeiro faça esta classe:

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

Em seguida, use isso na sua Atividade:

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

Isso permitirá que o usuário insira valores de 1 a 12 apenas .

EDIT:

Defina seu edittext com android:inputType="number".

Você pode encontrar mais detalhes em https://www.techcompose.com/how-to-set-minimum-and-maximum-value-in-edittext-in-android-app-development/ .

Obrigado.

Pratik Sharma
fonte
1
@mertaydin sure. experimente e me avise se precisar da minha ajuda. Obrigado.
Pratik Sharma
12
Aah, eu preciso de ajuda. Eu tenho um problema ao escrever o valor entre 1930 e 1999. Quando escrevo 1, ele está controlando o valor e 1 não está entre 1930 e 1999, portanto não o aceita.
mertaydin
1
@mertaydin Ei, desculpe, mas eu acendi um pouco ocupado com o meu trabalho. Eu só tenho tempo para analisar isso, acho que preciso fazer modificações no algoritmo aplicado na classe de filtro. Vou atualizá-lo assim que terminar.
Pratik Sharma
1
Alguns caracteres de sourcesubstituirão alguns caracteres em dest. Eu acho que você deve simular a substituição e obter o resultado final e validá-lo.
SD
3
@Pratik Sharma, Isto não funciona quando eu entrar variam de 1900 a 2000, pode sugerir algo
eminentes
89

Há um pequeno erro no código do Pratik. Por exemplo, se um valor for 10 e você adicionar 1 no início para fazer 110, a função de filtro tratará o novo valor como 101.

Veja abaixo uma correção para isso:

@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
fonte
Graças a isso me ajudou muito!
Jschplusa # 7/13
4
Eu acho que isso é mais claro 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. esta solução é mais correta do que aceita. Para verificar, por exemplo, tente usar InputFilterMinMax com a opção selectAllOnFocus ativada e compare o resultado.
precisa saber é o seguinte
1
Por que não String newVal= dest.toString().substring(0, dstart) + source.toString().substring(start, end) + dest.toString().substring(dend, dest.toString().length());, parece mais limpo e claro.
Shishir Gupta
5
Como mencionado por OP @mertaydin em um comentário sobre a resposta de @Patrick, esta solução ainda possui uma falha importante, pergunto-me por que não foi relatada: min==3se é impossível digitar qualquer número começando com 1 ou 2 (por exemplo: 15, 23)
Guerneen4
10

Do que eu vi da solução do @ Patrik e da adição do @ Zac, o código fornecido ainda tem um grande problema:

Se min==3for impossível digitar qualquer número começando com 1 ou 2 (ex: 15, 23)
Se min>=10for impossível digitar qualquer coisa, pois todo número terá que começar com 1,2,3 ...

No meu entendimento, não podemos alcançar a limitação min-max do EditTextvalor de um com o uso simples da classe InputFilterMinMax, pelo menos não para o valor min, porque quando o usuário está digitando um número positivo, o valor cresce e podemos facilmente executar um teste on-the-fly para verificar se atingiu o limite ou saiu do intervalo e bloqueia as entradas que não estão em conformidade. Testar o valor mínimo é uma história diferente, pois não podemos ter certeza se o usuário terminou de digitar ou não e, portanto, não podemos decidir se devemos bloquear ou não.

Não é exatamente o que o OP solicitou, mas para fins de validação eu combinei na minha solução um InputFilterpara testar os valores máximos e um OnFocusChangeListenerpara re-testar o valor mínimo quando EditTextperde o foco, assumindo que o usuário terminou de digitar e é algo assim:

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

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

        }
    }
}
}

Em Atividade, defina o InputFilterMaxe o OnFocusChangeListenerMinpara EditText observar: Você pode 2 in e max in onFocusChangeListener.

mQteEditText.setOnFocusChangeListener( new OnFocusChangeListenerMin('20');
mQteEditText.setFilters(new InputFilter[]{new InputFilterMax(getActivity(),'50')});
Guerneen4
fonte
OnFocusChangeListenerMin não está funcionando, é colocar todos os valores de zero
eminentes
1
Você se importaria em detalhar um pouco mais? o que você quer dizer com colocar todos os valores de zero ?
Guerneen4
a partir do código OnFocusChangeListenerMin deve ser acima de 20 trabalhando como discutido no problema bu aceitar todos os valores menores do que 20 como 0, 1, 2, etc ------ 19
eminente
Você achou alguma solução?
eminentes
Eu usei o OnFoncusChangeListener para fins de validação. No meu caso, eu mostro um erro no EditText notificar o usuário por um Toast que o valor não é bom e convido-o a inserir um novo valor. if(Integer.valueOf(val)<min){ //Notify user that the value is not good } Você pode fazer o que quiser, notificar o usuário e defina EditText como em branco, não sei se isso responde à sua pergunta
Guerneen4
9

Extensão da resposta de Pratik e Zac. Zac corrigiu um pequeno bug do Pratik em sua resposta. Mas notei que o código não suporta valores negativos; ele lançará uma NumberFormatException. Para corrigir isso e permitir que o MIN seja negativo, use o código a seguir.

Adicione esta linha (em negrito) entre as outras duas linhas:

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

if (newVal.equalsIgnoreCase ("-") && min <0) retorna 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
fonte
5

Se você precisar de um intervalo com números negativos como -90: 90, poderá usar esta solução.

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

Estendi o código @Pratik Sharmas para usar objetos BigDecimal em vez de ints, para que ele possa aceitar números maiores e levar em conta qualquer formatação no EditText que não seja um número (como formatação de moeda, como espaços, vírgulas e pontos)

EDIT: observe que esta implementação tem 2 como os valores mínimos significativos definidos no BigDecimal (consulte a constante MIN_SIG_FIG) como eu usei para moeda, portanto, sempre havia 2 números iniciais antes do ponto decimal. Altere a constante MIN_SIG_FIG conforme necessário para sua própria implementação.

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

Eu encontrei minha própria resposta. É muito tarde agora, mas quero compartilhar com você. Eu implemento esta interface:

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

}

E, em seguida, implemente-o dessa maneira dentro de sua atividade:

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 é uma resposta muito simples, se for o caso, por favor me diga.

Nash Makineta
fonte
int n = 0; é redundante. Uma vez que o valor padrão de n é 0.
Kenny Dabiri
1
Por que int n = 0 é redundante aqui? é uma variável local e não variável de instância aqui.
precisa saber é o seguinte
4

Há algo errado na resposta aceita.

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

Se eu mover o cursor para o meio do texto, digite algo, a instrução acima produzirá um resultado errado. Por exemplo, digite "12" primeiro, depois digite "0" entre 1 e 2; a declaração mencionada acima produzirá "120" em vez de 102. Modifiquei esta declaração para as declarações abaixo:

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

Kotlin se alguém precisar (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
    }
}

Então use isso da sua classe Kotlin

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

Este EditText permite de 1 a 100.

Em seguida, use isso no seu XML

android:inputType="number"
Alish
fonte
Estou usando a fonte de retorno e trabalho para mim ==> if (isInRange (min, max, input)) fonte de retorno
Muzafferus
3

Eu fiz uma maneira mais simples de definir um mínimo / máximo para um texto de edição. Eu uso o teclado aritmético e trabalho com 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());
    }
 }

O método aceita todos os seus valores, mas se um valor de usuários não aderir aos seus limites, ele será definido automaticamente para o limite mínimo / máximo. Por ex. limit limin = 10, limax = 80 se o usuário definir 8, automaticamente 10 será salvo em uma variável e EditText como 10.

Argyris
fonte
3

Eu sei que já existem um milhão de respostas para isso, com uma aceita. No entanto, existem inúmeros erros na resposta aceita e a maioria dos demais simplesmente corrige um (ou talvez dois) deles, sem expandir para todos os casos de uso possíveis.

Então, eu basicamente compilei a maioria das correções sugeridas nas respostas de suporte, além de adicionar um método para permitir a entrada contínua de números fora do intervalo na direção de 0 (se o intervalo não começar em 0), pelo menos até que seja certo de que não pode mais estar no intervalo. Porque, para ficar claro, este é o único momento que realmente causa problemas em muitas das outras soluções.

Aqui está a correção:

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

}

Observe que é impossível lidar com alguns casos de entrada "ativamente" (ou seja, como o usuário está inserindo), portanto, devemos ignorá-los e tratá-los depois que o usuário terminar de editar o texto.

Veja como você pode usá-lo:

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

Agora, quando o usuário tentar digitar um número mais próximo de 0 do que o intervalo permite, uma das duas coisas acontecerá:

  1. Se mine maxtiverem o mesmo número de dígitos, eles não terão permissão para inseri-lo assim que chegarem ao dígito final.

  2. Se um número fora do intervalo for deixado no campo quando o texto perder o foco, ele será ajustado automaticamente para o limite mais próximo.

E, é claro, o usuário nunca poderá inserir um valor além de 0 do que o intervalo permite, nem é possível que um número como esse "acidentalmente" esteja no campo de texto por esse motivo.

Problemas conhecidos

  1. Isso só funciona se o EditTextfoco for perdido quando o usuário terminar.

A outra opção é desinfetar quando o usuário pressiona a tecla "concluído" / retornar, mas em muitos ou até na maioria dos casos, isso causa uma perda de foco de qualquer maneira.

No entanto, fechar o teclado virtual não desvira o foco automaticamente do elemento. Tenho certeza de que 99,99% dos desenvolvedores do Android gostariam que sim (e que o manuseio do foco nos EditTextelementos era menos desagradável em geral), mas até o momento não há nenhuma funcionalidade integrada para isso. O método mais fácil que eu encontrei para contornar isso, se necessário, é estender EditTextalgo assim:

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

Isso "engana" o filtro para higienizar a entrada, mesmo que a visualização não tenha realmente perdido o foco. Se, posteriormente, a visão perder o foco por conta própria, o saneamento de entrada será acionado novamente, mas nada mudará, pois já foi corrigido.

Encerramento

Ufa. Isso foi muito. O que originalmente parecia ser um problema trivialmente fácil acabou descobrindo muitos pedaços feios de baunilha Android (pelo menos em Java). E mais uma vez, você só precisa adicionar o ouvinte e estender EditTextse o seu intervalo não incluir 0 de alguma forma. (E realisticamente, se seu intervalo não incluir 0, mas começar em 1 ou -1, você também não terá problemas.)

Como última nota, isso funciona apenas para ints . Certamente, existe uma maneira de implementá-lo para trabalhar com decimais ( double, float), mas, como nem eu nem o solicitante original precisamos disso, não quero aprofundar muito nisso. Seria muito fácil simplesmente usar a filtragem pós-conclusão junto com as seguintes linhas:

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

Você teria apenas que mudar de intpara float(ou double), permitir a inserção de um único .(ou ,, dependendo do país?) E analisar como um dos tipos decimais em vez de um int.

Isso lida com a maior parte do trabalho de qualquer maneira, portanto, funcionaria de maneira muito semelhante.

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

Exemplo muito simples no Kotlin:

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

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

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

por favor verifique 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 o link abaixo para obter mais detalhes sobre o edittext e os edittextfilteres com o observador de texto.

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

itsrajesh4uguys
fonte
O OP deseja validá-lo quando o valor estiver sendo inserido. Eu acho que você forneceu solução para o cenário depois de valor é inserido
MysticMagicϡ
Eu não sou o questionador. Eu tinha apenas dúvidas sobre sua resposta, então estava esclarecendo.
precisa saber é o seguinte
Não quero verificar a contagem de caracteres. Eu acho que você está tentando verificar a contagem neste código: if (TextUtils.isEmpty (pass) || pass.length <[YOUR MIN LENGTH]) Limito apenas o valor, por exemplo, o valor do mês, o usuário deve escrever o valor entre 1-12, não 13,14 ou etc. Portanto, 12,13,14, até 99 ter 2 caracteres.
mertaydin
oi @mertaydin você tentou com o link que eu lhe forneci .. veja esse exemplo .. pode ser isso que você deseja. ele vai assistir o texto enquanto você está entrando ..
itsrajesh4uguys
Ok obrigado, vou tentar sua resposta e a resposta de @Pratik Sharma.
mertaydin
1

Se você está preocupado apenas com o limite máximo, basta adicionar a linha abaixo

android:maxLength="10" 

Se você precisar adicionar um limite mínimo, nesse caso, o limite mínimo é 7. o usuário está restrito a inserir caracteres entre o limite mínimo e máximo (entre 8 e 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();
        }
    }

Se você também precisar restringir o usuário a inserir 01 no início, modifique se a condição for desta maneira

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

No final da chamada, como

   ....else if (!(Helper.isValidMobilePhone(textMobileNo))){
                        Helper.setEditTextError(etMobileNo,"Invalid Mobile Number");
                    }......
Faakhir
fonte
2
Isso não é vlaue, é comprimento
portfoliobuilder
1

@Pratik Sharma

Para números negativos de suporte , adicione o seguinte código no 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;
  }

}

Em seguida, use isso na sua Atividade:

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

Defina seu edittext com:

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

// ainda tem algum problema, mas aqui você pode usar min, max em qualquer faixa (positiva ou negativa)

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

Para adicionar à resposta do Pratik, aqui está uma versão modificada na qual o usuário pode digitar min 2 dígitos também, por exemplo, 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;
    }}

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

Espero que isto ajude. gentilmente não voto negativo sem motivos.

sanjeeb
fonte
0

aqui está o jeito que eu usei, está trabalhando para um número negativo

Primeiro, crie a classe MinMaxFIlter.java com o seguinte 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;
    }
}
}

Em seguida, crie e defina seu filtro para seu edittext assim:

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

este é o meu 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
fonte
0

Você pode fazer isso com um InputFilter. Aparentemente, existe apenas essa interface de filtro de entrada que você pode usar. Antes de fazer isso da maneira irritante e criar uma nova classe que estenda o filtro de entrada, você pode usar esse atalho com uma instanciação da interface da classe interna.

Portanto, você apenas faz isso:

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

                    }
                }
        });

Neste exemplo, verifico se o valor do EditText é maior que 8. Caso contrário, ele deve ser definido como 8. Portanto, é necessário que você consiga acompanhar o mínimo máximo ou a lógica do filtro. Mas pelo menos você pode escrever a lógica do filtro de maneira bem organizada e curta diretamente no EditText.

Espero que isto ajude

Christopher-Robin Fey Feysenbe
fonte
0

Para definir o valor mínimo do EditText, usei isso:

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

O código do @ Patrik tem uma boa idéia, mas com muitos erros. @Zac e @Anthony B (soluções de números negativos) resolveram alguns deles, mas o código de @ Zac ainda possui 3 erros principais:

1. Se o usuário excluir todas as entradas no EditText, é impossível digitar qualquer número novamente. É claro que isso pode ser controlado usando um ouvinte alterado EditText em cada campo, mas apagará a beleza de usar uma classe InputFilter comum para cada EditText no seu aplicativo.

2. O @ Guernee4 diz que, por exemplo min = 3, é impossível digitar qualquer número começando com 1.

3. Se, por exemplo, min = 0, você pode digitar quantos zeros desejar, o resultado não é elegante. Ou também, se não importa qual é o valor mínimo, o usuário pode colocar o cursor no tamanho esquerdo do primeiro número, colocar vários zeros à esquerda, também não é elegante.

Eu vim com essas pequenas mudanças no código do @ Zac para resolver esses 3 bugs. Em relação ao bug nº 3, ainda não consegui remover completamente todos os zeros à esquerda; Sempre pode ser um, mas um 00, 01, 0100 etc, nesse caso, é mais elegante e válido que um 000000, 001, 000100, etc.etc. Etc.

Aqui está o 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 "";
    }

Tenha um bom dia!

nnyerges
fonte
-1

Aqui está minha opinião sobre a resposta de Pratik Sharma Kotline Doublese alguém precisa

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
fonte
Este filtro de entrada é errado, ele ignora o início, fim DStart, índices DEND do texto, então se você mudar o texto editar através da inserção de um personagem no meio não vai funcionar corretamente
Radu