有没有办法在Android中为EditText定义最小值和最大值?

mer*_*din 121 android android-edittext

我想定义一个最小值和最大值EditText.

例如:如果任何人试图在其中输入月份值,则该值必须介于1-12之间.

我可以通过使用来实现,TextWatcher但我想知道在布局文件或其他地方是否有其他方法可以做到这一点.

编辑:我不想限制字符数.我想限制价值.例如,如果我EditText在输入12时限制月份w字符,它将接受它,但如果我输入22,则在我进入时不得接受它.

Pra*_*rma 270

先做这个课:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在您的Activity中使用它:

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

这将允许用户输入1到12之间的值.

编辑:

使用设置您的edittext android:inputType="number".

谢谢.

  • 啊,我需要帮助.我在1930年和1999年之间的写入值时遇到了问题.当我写1它控制值而1不在1930和1999之间时所以它不接受它. (11认同)
  • @Pratik Sharma,当我进入1900年至2000年的范围时,这不起作用,你能提出一些建议 (3认同)
  • 对于最小值= 20和最大值= 30不起作用 (3认同)

Zac*_*Zac 82

Pratik的代码中有一个小错误.例如,如果值为10并且您在开头添加1以生成110,则过滤器函数会将新值视为101.

请参阅下面的解决方案:

@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 "";
}
Run Code Online (Sandbox Code Playgroud)

  • 正如OP @mertaydin在评论@Patrick的回答中提到的那样,这个解决方案仍有一个重大缺陷,我想知道为什么没有报道:如果`min == 3`那么就不可能输入任何数字开头1或2(例如:15,23) (5认同)
  • 我认为这更清楚_imho_:`String replacement = source.subSequence(start,end).toString(); String newVal = dest.subSequence(0,dstart).toString()+ replacement + dest.subSequence(dend,dest.length()).toString();` (4认同)
  • +1。这个解决方案比接受的更正确。要检查它,例如尝试使用 **InputFilterMinMax** 并启用 **selectAllOnFocus** 选项并比较结果。 (2认同)
  • 为什么不 `String newVal= dest.toString().substring(0, dstart) + source.toString().substring(start, end) + dest.toString().substring(dend, dest.toString().length( ));`,看起来更干净、清晰。 (2认同)

Gue*_*en4 10

我所看到的@ Patrik的解决方案和@Zac的补充,提供的代码仍有一个大问题:

如果min==3那么就不可能输入以1或2开头的任何数字(例如:15,23)
如果min>=10那么就不可能输入任何数字,因为每个数字必须以1,2,3开头...

在我的理解中,我们无法EditText通过简单使用类来实现最小值的限制InputFilterMinMax,至少不能达到最小值,因为当用户键入正数时,值会增加,我们可以轻松地执行即时测试,以检查它是否达到限制或超出范围并阻止不符合条目.测试最小值是一个不同的故事,因为我们无法确定用户是否已完成输入,因此无法决定是否应该阻止.

这不是OP所要求的,但为了验证的目的,我已经在我的解决方案中结合InputFilter测试最大值,OnFocusChangeListenerEditText失去焦点时重新测试最小值,假设用户已完成输入并且它是这样的:

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 "";
}
}
Run Code Online (Sandbox Code Playgroud)

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
            }

        }
    }
}
}
Run Code Online (Sandbox Code Playgroud)

然后,在活动设置InputFilterMaxOnFocusChangeListenerMinEditText 注:您可以2都最小和最大的onFocusChangeListener.

mQteEditText.setOnFocusChangeListener( new OnFocusChangeListenerMin('20');
mQteEditText.setFilters(new InputFilter[]{new InputFilterMax(getActivity(),'50')});
Run Code Online (Sandbox Code Playgroud)


Ant*_*y B 9

延伸Pratik和Zac的答案.Zac在他的回答中修复了一个Pratik的小虫子.但我记得代码不支持负值,它会抛出NumberFormatException.要解决此问题,并允许MIN为负数,请使用以下代码.

在另外两行之间添加此行(以粗体显示):

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

if(newVal.equalsIgnoreCase(" - ")&& min <0)返回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 "";
}
Run Code Online (Sandbox Code Playgroud)


小智 9

如果有人需要 Kotlin(使用实用程序)

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
    }
}
Run Code Online (Sandbox Code Playgroud)

然后从您的 Kotlin 课程中使用它

percentage_edit_text.filters = arrayOf(Utilities.InputFilterMinMax(1, 100))
Run Code Online (Sandbox Code Playgroud)

此 EditText 允许 1 到 100。

然后从您的 XML 中使用它

android:inputType="number"
Run Code Online (Sandbox Code Playgroud)


And*_*oob 5

我将@Pratik Sharmas代码扩展为使用BigDecimal对象而不是整数,以便它可以接受更大的数字,并且可以解释EditText中不是数字的任何格式(如货币格式,即空格,逗号和句点)

编辑:请注意,此实现有2作为BigDecimal上设置的最小有效数字(请参阅MIN_SIG_FIG常量),因为我将其用作货币,因此小数点前总是有2个前导数字.根据您自己的实现需要更改MIN_SIG_FIG常量.

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;
}
Run Code Online (Sandbox Code Playgroud)


Den*_*nko 5

如果您需要带负数的范围,如-90:90,则可以使用此解决方案.

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;
}
}
Run Code Online (Sandbox Code Playgroud)


Nas*_*eta 5

我找到了我自己的答案。现在已经很晚了,但我想与您分享。我实现了这个接口:

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

}
Run Code Online (Sandbox Code Playgroud)

然后在您的活动中以这种方式实现它:

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();
            }
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

这是一个非常简单的答案,如果有更好的请告诉我。