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

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

例如: 如果任何人试图在其中输入一个月值,该值必须在1-12之间。

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

编辑: 我不想限制角色数量。我想限制价格。例如,如果我限制月 EditTextw 字符时,我输入12它将接受它,但如果我输入22它不能接受它,而我输入。

160301 次浏览

首先上这门课:

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

然后从你的活动中使用这个:

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

这将允许用户输入 只能从1到12

编辑:

android:inputType="number"设置编辑文本。

你可以在 https://www.techcompose.com/how-to-set-minimum-and-maximum-value-in-edittext-in-android-app-development/找到更多的细节。

谢谢。

请检查这个代码

    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
}

使用下面的链接了解更多关于编辑文本和编辑文本过滤器的详细信息。

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

普拉提克的代码有个小错误。例如,如果一个值为10,并且在开始处加上1使之为110,则 filter 函数将把新值视为101。

请看下面的解决方案:

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
try {
// Removes string that is to be replaced from destination
// and adds the new string in.
String newVal = dest.subSequence(0, dstart)
// Note that below "toString()" is the only required:
+ source.subSequence(start, end).toString()
+ dest.subSequence(dend, dest.length());
int input = Integer.parseInt(newVal);
if (isInRange(min, max, input))
return null;
} catch (NumberFormatException nfe) { }
return "";
}

我扩展了@Pratik Sharmas 代码,使用 BigDecimal 对象代替 int,这样它就可以接受更大的数字,并解释 EditText 中任何不是数字的格式(比如货币格式,比如空格、逗号和句点)

编辑: 注意,这个实现在 BigDecimal (参见 MIN _ SIG _ FIG 常数)上设置了2作为最小有效数字,因为我将它用于货币,所以在小数点之前总是有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;
}

我制定了一个更简单的方法来设置一个 min/max 到一个 Edittext。我使用算术键盘,并使用这种方法:

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

该方法接受您的所有值,但如果用户的值不符合您的限制,它将自动设置为最小/最大限制。 为了前任。Limit limin = 10,limax = 80,如果用户设置为8,则自动将10保存为一个变量,EditText 设置为10。

对于@Patrik 的解决方案和@Zac 的添加,我所看到的代码仍然存在一个大问题:

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

在我的理解中,我们不能简单地使用类 InputFilterMinMax来实现 EditText值的最小-最大限制,至少不能实现最小值,因为当用户键入一个正数时,值会增长,我们可以很容易地执行一个动态测试来检查它是否达到了极限或超出了范围,并阻止不符合的条目。测试 min 值是另一回事,因为我们不能确定用户是否已经完成键入,因此不能决定是否应该阻塞。

这不完全是 OP 要求的,但为了验证的目的,我已经在我的解决方案中组合了一个 InputFilter来测试最大值,一个 OnFocusChangeListener来重新测试最小值,当 EditText失去焦点时,假设用户已经完成输入,它是这样的:

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

还有 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
}


}
}
}
}

然后在活动设置 InputFilterMaxOnFocusChangeListenerMinEditText 注意: 在 onFocusChangeListener中可以同时使用2分钟和最大值。

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

如果你只关心最大限制,那么只需添加下面的行

android:maxLength="10"

如果你需要添加最小限制,那么你可以这样做,在这种情况下,最小限制是7。用户只能输入最小和最大限制之间的字符(在8和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();
}
}

如果您还需要限制用户在开始时输入01,然后像这样修改 If 条件

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

在结束调用方法时,如

   ....else if (!(Helper.isValidMobilePhone(textMobileNo))){
Helper.setEditTextError(etMobileNo,"Invalid Mobile Number");
}......

如果需要 -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;
}
}

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

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


}

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

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

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

//仍然有一些问题,但是在这里您可以在任何范围(正或负)使用 min、 max

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

为了补充 Pratik 的答案,这里有一个修改过的版本,用户可以输入最小2位数,例如,15到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;
}}

如果(结束 = = 1) Min = Integer.parseInt (source. toString ()) ;

希望这个能帮上忙。 请不要无缘无故地否决投票。

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

扩展了普拉提克和扎克的回答。扎克在回答中修正了普拉提克的一个小错误。但是我注意到代码不支持负值,它会抛出 NumberFormatException。要修复这个问题,并允许 MIN 为负值,请使用以下代码。

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

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

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

这个被接受的答案有问题。

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

如果我将光标移动到文本中间,然后键入一些内容,那么上面的语句将产生错误的结果。 例如,首先键入“12”,然后在1和2之间键入“0”,然后上面提到的语句将生成“120”而不是102。 我将本发言修改为以下发言:

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

我知道这个问题已经有一百万个答案了,只有一个被接受。然而,在可接受的答案中存在大量的 bug,其余的大多数只是修复其中的一个(或者两个) ,而没有扩展到所有可能的用例。

因此,我基本上编译了支持答案中建议的大部分 bug 修复,并添加了一个方法,允许在0的方向连续输入范围之外的数字(如果范围不是从0开始的) ,至少在确定它不再在范围之内之前。因为要清楚,这是唯一一次真正导致麻烦的许多其他解决方案。

解决办法是:

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


}

注意,有些输入情况不可能处理“主动”(即,当用户输入时) ,因此我们必须忽略它们,并在用户完成文本编辑后处理它们。

你可以这样使用它:

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

现在,当用户试图输入一个比范围允许的接近0的数字时,会发生以下两种情况之一:

  1. 如果 minmax有相同数量的数字,他们将不会被允许输入它一旦他们到达最后的数字。

  2. 如果当文本失去焦点时,范围之外的数字留在字段中,它将自动调整到最接近的边界。

当然,用户永远不会被允许输入距离0超过允许范围的值,也不可能因为这个原因而“意外”出现在文本字段中。

已知问题

  1. 这只有在用户使用完 EditText后,EditText失去焦点时才有效。

另一个选项是当用户点击“ done”/return 键时进行消毒,但是在许多情况下,甚至在大多数情况下,这会导致焦点的丢失。

但是,关闭软键盘将 没有自动取消该元素的焦点。我相信99.99% 的 Android 开发人员都希望这样(而且对 EditText元素的专注处理一般来说不会陷入困境) ,但是到目前为止还没有内置的功能。如果需要的话,我找到的解决这个问题的最简单的方法是扩展 EditText,如下所示:

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

这将“欺骗”过滤器进入消毒的输入,即使视图没有 事实上失去焦点。如果视图后来失去了自己的焦点,输入环境卫生将再次触发,但是因为它已经被修复,所以什么都不会改变。

关门

呼。好多啊。最初看起来很简单的问题,最终却发现了许多普通的 Android (至少在 Java 中是这样)的丑陋片段。同样,如果范围在某种程度上不包括0,那么只需要添加侦听器并扩展 EditText(实际上,如果范围不包括0,而是从1或 -1开始,也不会遇到问题。)

最后一点,这只适用于 整数。当然有一种方法可以实现它来处理小数(doublefloat) ,但是因为我和最初的提问者都不需要它,所以我并不特别想深入了解它。简单地使用完成后过滤和以下内容是非常容易的:

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

您只需要将 int改为 float(或 double) ,允许插入单个 .(或 ,,取决于国家?),并将其解析为十进制类型之一,而不是 int

无论如何,它处理了大部分工作,所以它的工作方式非常相似。

这是我使用的方法,它对负数起作用

首先,用以下代码创建 MinMaxFIlter.java 类:

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

然后,像下面这样创建并设置您的过滤器到您的编辑文本:

EditText edittext = new EditText(context);
editext.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED);
eInt.setFilters(new InputFilter[]{new MinMaxFilter(min, max)});

这是我的代码 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" />

爪哇咖啡

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


}
});

@ Pratik Sharma

为了支持 负数,在 过滤器方法中添加以下代码:

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


}

然后从你的活动中使用这个:

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

将您的编辑文本设置为:

android:inputType="number|numberSigned"

关于科特林的一个很简单的例子:

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

您可以使用 InputFilter 完成此操作。显然,只有这个输入过滤器接口您可以使用。在使用创建扩展 Input 筛选器的新 Class 的恼人方法之前,可以使用这个快捷方式实例化内部类 Interface。

因此,你只需要这样做:

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


}
}
});

在这个示例中,我检查 EditText 的值是否大于8。如果没有,应设置为8。所以显然你需要自己想出最小最大值或者其他什么过滤逻辑。但至少您可以将过滤器逻辑非常整洁和简短地直接写入 EditText。

希望这个能帮上忙

为了定义 EditText 的最小值,我使用了以下内容:

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

如果有人需要的话,以下是我对夏尔马 KotlinDouble的回答的看法

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

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

那就用你科特林课上学到的

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

此 EditText 允许从1到100。

然后从您的 XML 中使用它

android:inputType="number"

@ Patrik 的代码有个好主意,但是有很多漏洞。 @ Zac 和@Anthony B (负数解决方案)已经解决了其中一些问题,但是@Zac 的代码仍然有3个主要的 bug:

1. 如果用户删除 EditText 中的所有条目,就不可能再次键入任何数字。.当然,这可以通过在每个字段上使用 EditText 更改的侦听器来控制,但是它会抹去对应用程序中的每个 EditText 使用通用 InputFilter 类的好处。

2. Has@Guernee4说,如果例如 min = 3,就不可能输入任何以1开头的数字。

3. 如果例如 min = 0,您可以输入许多您希望的零,这样结果就不优雅了。或者,如果不管最小值是什么,用户都可以把光标放在第一个数字的左边大小,左边放一堆前导零,也不雅观。

我对@Zac 的代码做了一些小小的修改,解决了这3个 bug。关于 bug # 3,我仍然不能完全去除左边的所有前导零; 它总是可以是1,但是在这种情况下,一个00,01,0100等等,比一个000000,001,000100等等更优雅有效。等等。

密码如下:

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

祝你愉快!

我在做一个宠物项目时偶然发现了这个问题。 我已经阅读了这里的一些答案,并且可能已经在我的代码中采用了其中的一两个。

坏消息: 我通过一种非常肮脏的方式做到了这一点(你会知道为什么)。还有一些 bug 我没有去解决(我在凌晨2点写这篇文章) ,比如如果 min值是10,你就不能从一开始就输入一个数字。

好消息: 我已经设法消除了@nnyerges 提到的前导0错误,仅仅使用 InputFilter下降到只有一个0,即如果 min值为0。然而,当用户删除后面跟着零的第一个数字时,我的 InputFilter实现的限制就出现了,例如,如果第一个用户输入 1000,然后删除 1,它就会变成 000。这就是我对 TextChangedListener/TextWatcher肮脏丑陋的使用的原因。(我知道 OP 已经说过他可以使用 TextWatcher来完成,不过无所谓了。)
另一个限制(或者可能是 我的限制?)使用 InputFilter是指当 inputTypenumberDecimal时,这意味着用户可以输入一个小数点。例如: 范围是 0 - 100,用户输入 99.99,用户然后删除分隔符,我们将有 9999。我们不想那样,对吧?
我也到了 适应负值

我的代码中的一些特性,不管你喜欢与否,包括修剪不重要的 0,例如,如果用户从 10032中删除 1,只要它在规定的范围内,它就会修剪前面的 0,所以最终的结果是32。其次,当用户尝试删除负数(-)或小数点(.)时,它会检查删除后的结果数字是否仍在范围内。如果不是,那么它将恢复到最后一个值。换句话说,用户不允许进行这种删除操作。但是,如果你喜欢设置新的值为 minmax的值,当这种情况发生时,你也可以这样做。

注意: 我懒得进行本地化,所以使用逗号作为小数点的人必须自己手动更改。
第二个注意: 代码非常混乱,可能有一些或许很多冗余的检查,所以要注意。此外,如果你有建议,请随时评论,因为我也想改进它。我以后可能需要用到它。谁知道呢?

不管怎样,开始了。

import android.text.InputFilter;
import android.text.Spanned;
import android.util.Log;


public class InputFilterMinMax implements InputFilter {
    

private double min, max;
    

public InputFilterMinMax(double min, double max) {
this.min = min;
this.max = max;
}
    

public InputFilterMinMax(String min, String max) {
this.min = Double.parseDouble(min);
this.max = Double.parseDouble(max);
}
    

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
try {
String lastVal = dest.toString();
String newVal = lastVal.substring(0, dstart) + source.toString() + lastVal.substring(dstart);
String strInput = source.toString();
double input;
    

if (strInput.equals("-") && (lastVal.length() == 0 || lastVal.equals("0"))) {
return null;
} else {
input = Double.parseDouble(newVal);
}
            

if (isInRange(min, max, input)) {
try {
if (lastVal.equals("0") && strInput.equals("0") && !strInput.equals(".")) {
Log.d("Checkpoint 1", "Can't put 0 again.");
return "";
} else if (strInput.equals("0")) {
if (dstart == 0) {
if (lastVal.substring(0, 1).equals("0")) {
Log.d("Checkpoint 2", "Can't put 0 again.");
return "";
} else if (!lastVal.substring(0, 1).equals(".")) {
Log.d("Checkpoint 3", "Can't put 0 in front of them.");
return "";
}
} else {
if (lastVal.substring(0, 1).equals("0") && dstart == 1) {
Log.d("Checkpoint 4", "Can't put 0 again.");
return "";
} else if (lastVal.substring(0, 1).equals("-")) {
if (Double.parseDouble(lastVal) == 0) {
if (!lastVal.contains(".")) {
Log.d("Checkpoint 5", "Can't put 0 here.");
return "";
} else {
if (dstart <= lastVal.indexOf(".")) {
Log.d("Checkpoint 6", "Can't put 0 here.");
return "";
}
}
} else {
if (lastVal.indexOf("0") == 1 && (dstart == 1 || dstart == 2)) {
Log.d("Checkpoint 7", "Can't put 0 here.");
return "";
} else if ((!lastVal.substring(1, 2).equals("0") && !lastVal.substring(1, 2).equals(".")) && dstart == 1) {
Log.d("Checkpoint 8", "Can't put 0 here.");
return "";
}
}
}
}
}
    

/**
* If last value is a negative that equals min value,
* and user tries to input a decimal separator at the
* very end, ignore it, because they won't be able to
* input anything except 0 after that anyway.
*/
if (strInput.equals(".") && lastVal.substring(0,1).equals("-")
&& Double.parseDouble(lastVal) == min && dstart == lastVal.length()) {
return "";
}
} catch (Exception e) {
}
return null;
}
} catch (Exception ignored) {
ignored.printStackTrace();
}
return "";
}
    

private boolean isInRange(double a, double b, double c) {
return b > a ? c >= a && c <= b : c >= b && c <= a;
}
}

现在,真正肮脏的部分:

import androidx.appcompat.app.AppCompatActivity;


import android.os.Bundle;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextWatcher;
import android.util.Log;
import android.widget.EditText;


public class MainActivity extends AppCompatActivity implements TextWatcher {
    

private EditText editInput;
    

/**
* Var to store old value in case the new value is either
* out of range or invalid somehow. This was because I
* needed a double value for my app, which means I can
* enter a dot (.), and that could mean trouble if I decided
* to delete that dot, e.g. assume the range is 0 - 100.
* At first I enter 99.99, the InputFilter would allow that,
* but what if somewhere down the line I decided to delete
* the dot/decimal separator for "fun"?
* Wow, now I have 9999.
* Also, when I delete negative notation, it can produce
* the same problem.
*/
private String oldVal;
    

private int min, max;
    

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
        

editInput = findViewById(R.id.edt_input);
editInput.addTextChangedListener(this);
        

min = -1600;
max = 1500;
        

editInput.setFilters(new InputFilter[]{new InputFilterMinMax(min, max)});
}
    

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
oldVal = saveOldValue(s, start);
}
    

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
    

}
    

@Override
public void afterTextChanged(Editable s) {
validateChange(editInput, oldVal);
}
    

private String saveOldValue(CharSequence s, int start) {
String oldVal = s.toString();
if (oldVal.contains(".") && start == oldVal.indexOf(".") && start != oldVal.length() - 1) {
return oldVal;
} else if (oldVal.contains("-") && start == oldVal.indexOf("-") && start != oldVal.length() - 1) {
return oldVal;
}
return null;
}
    

private void validateChange(EditText editText, String oldVal) {
String strNewVal = editText.getText().toString().trim();
boolean isChanged = false;


if (strNewVal.indexOf("0") == 0 || (strNewVal.indexOf("-") == 0 && strNewVal.indexOf("0") == 1)) {
if (strNewVal.contains(".")) {
while ((strNewVal.indexOf("0") == 0 && strNewVal.indexOf(".") != 1 && strNewVal.length() > 2) ||
(strNewVal.indexOf("0") == 1 && strNewVal.indexOf(".") != 2 && strNewVal.length() > 3)) {
Log.d("Trimming 0", "");
strNewVal = strNewVal.replaceFirst("0", "");
isChanged = true;
}
} else if (!strNewVal.contains(".")) {
while (strNewVal.indexOf("0") == 0 && strNewVal.length() > 1) {
Log.d("Trimming 0", "");
strNewVal = strNewVal.replaceFirst("0", "");
isChanged = true;
}


if (Double.parseDouble(strNewVal) > max) {
editText.setText(oldVal); // Or, you can set it to max values here.
return;
}
}
}
        

if (strNewVal.indexOf(".") == 0) {
strNewVal = "0" + strNewVal;
isChanged = true;
}


try {
double newVal = Double.parseDouble(strNewVal);
Log.d("NewVal: ", String.valueOf(newVal));
if (newVal > max || newVal < min) {
Log.d("Over Limit", "Let's Reset");
editText.setText(oldVal); // Or, you can set it to min or max values here.
}
} catch (NumberFormatException e) {
e.printStackTrace();
}


if (isChanged) {
editText.setText(strNewVal);
}
}
}

首先创建一个方法,如下所示

private InputFilter inRange(int min, int max) {
return new InputFilter(){
@Override
public CharSequence filter(CharSequence source, int start1, int end, Spanned dest, int dstart, int dend) {
try {
int input = Integer.parseInt(dest.toString() + source.toString());
if (input < min || input > max){
return "";
} else {
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
};
}

像这样使用它:

edittext1.setFilters(new InputFilter[]{inRange(3,60)});
edittext2.setFilters(new InputFilter[]{inRange(1,100)});

你可以像这样做更多的归档和添加:

edittext1.setFilters(new InputFilter[]{filter1(somevalue),filter2(somevalue)});

这里的许多解决方案都很棒,但我想提供一个更快的替代方案,如果你只是在寻找一种防止溢出的方法,那么这个方案可能就足够了:

android:maxLength="9"

这将确保您无法获得非小数的32位整数溢出。这里的最小值是 -99999999,最大值是 999999999

在 Kotlin:

class InputFilterMinMax(private val min: Float, private val max: Float) : InputFilter {


override fun filter(source: CharSequence, start: Int, end: Int, dest: Spanned, dstart: Int, dend: Int): CharSequence? {
try {
val input = (dest.subSequence(0, dstart).toString() + source + dest.subSequence(dend, dest.length)).toFloat()
if (isInRange(min, max, input)) return null
} catch (e: NumberFormatException) {
e.printStackTrace()
}
return ""
}


private fun isInRange(a: Float, b: Float, c: Float): Boolean {
return if (b > a) c in a..b else c in b..a
}
}