android-edittext edittext监听输入 - 有没有办法在Android中为EditText定义最小值和最大值?





edittext样式 edittext获取内容 (15)


这是我用过的方式,它用于负数

首先,用下面的代码创建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)});

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

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

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

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




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



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

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



要添加到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;
    }}

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

希望这可以帮助。 请不要无理由地downvote。




请检查此代码

    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 
  }

请使用以下链接了解更多关于edittext的信息,以及edittextfilteres与文本观察者的关系。

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




我做了一个更简单的方法来将最小/最大值设置为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());
    }
 }

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




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

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

根据我的理解,我们无法通过简单使用类InputFilterMinMax来实现EditText值的最小 - 最大限制,至少不是最小值,因为当用户输入正数时,值越来越大,我们可以轻松地进行实时测试以检查是否达到限制或超出范围并阻止不符合条目。 测试最小值是一个不同的故事,因为我们无法确定用户是否已完成打字,因此无法确定是否应该阻止。

这不是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
            }

        }
    }
}
}

然后在Activity中将InputFilterMaxOnFocusChangeListenerMinEditText注意:您可以在onFocusChangeListener同时设置min和max。

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



接受的答案中有错误。

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



我知道有一百万个答案已经被接受。 但是,接受的答案中存在许多错误,其余大部分错误只修复其中的一个(或者两个),而没有扩展到所有可能的用例。

所以我基本编译了支持答案中提出的大多数错误修复,并添加了一种方法,允许在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. 如果文本失去焦点时,范围之外的数字会留在字段中,则会自动调整为最接近的边界。

当然,用户决不允许输入比范围允许的值更远的值,也不可能出于这个原因“意外地”出现在文本字段中的数字。

已知的问题?)

  1. 这只在EditText在用户完成时失去焦点时才起作用。

另一种选择是在用户点击“完成”/返回键时进行消毒,但在许多情况下甚至大多数情况下,这会导致焦点丢失。

但是,关闭软键盘不会自动取消对焦元素。 我相信有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;

您只需要将intint更改为float (或double ),即可插入一个. (或者,取决于国家?),并且解析为小数类型之一而不是int

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




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

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

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




首先让这个类:

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"设置你的edittext。

谢谢。




Pratik的扩展和Zac的答案。 Zac在他的回答中修复了一个小小的Pratik's bug。 但我没注意到代码不支持负值,它会抛出一个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 "";
}



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









android android-edittext