3

I am looking for a way to limit the numbers I enter into the EditText field, but I am encountering some obstacles.

I have already thoroughly researched for a solution to my problem, which I will define specifically below.

I want to create 4 different EditText fields in which each accepts the following ranges: (1, 24); (80, 200); (1, 999); (40, 70).

These, for simplicity, will not be decimals (or doubles/floats/longs) but only integers.

I have looked into the solutions provided by the following links, and have provided their shortcomings.

Android: Limiting EditText to numbers This solution only tells me how to limit the entered text to numerical data only. It does not provide ranges.

Is there a way to define a min and max value for EditText in Android? The accepted solution does accomplish the goal of setting the range, but the problem is that it only works for the ranges (1, 24) and (1, 999) due to its implementation. The problem is that if I look for values in the intervals (40, 70) or (80, 200), I will start by entering one digit at a time, so this does not work. It will deny the single digit input, which makes it non-user friendly.

How to limit the text in numbers only from 0-59 in Edit Text in Android? I believe the accepted solution here has the same problem as the one above, since it takes one digit at a time. I considered using the same method under afterTextChanged instead on onTextChanged, but to no avail.

Number range on an edittext - only want numbers between 1 and 10 This solution involves a button click to evaluate whether the number falls in the given range, so this would be considered an "after-the-fact" solution. I need an EditText that rejects the user's input in real time.

Your assistance is greatly appreciated and will probably help resolve the problems that many others have apparently had (reading the comments, others seem to want ranges that don't start/end in single-digit numbers).

Community
  • 1
  • 1
DLuciferin
  • 71
  • 2
  • 7
  • Take a look at this one. http://stackoverflow.com/questions/14212518/is-there-any-way-to-define-a-min-and-max-value-for-edittext-in-android – mariozawa Feb 19 '16 at 03:37
  • That one I have already covered. It's #2. – DLuciferin Feb 19 '16 at 03:40
  • I can't imagine a very effective method for achieving a real-time evaluation since, as you said, the input is entered one digit at a time. If you're not opposed to using Spinners, you could define the values to be included and merely have the user select one, but with EditText you may be s.o.l. – Calvin P. Feb 19 '16 at 03:45
  • I am opposed to using Spinners because the range of values is quite large. Based on my little experience, I can't imagine having a range of 80-200 (that's 121 integers, inclusive) fit into a single spinner on a phone screen. But thank you for pointing out that possibility. – DLuciferin Feb 19 '16 at 03:47
  • (Regarding #2 link) I would also like to note that I have looked at the non-accepted answers on that page. Specifically, Guerneen4's solution and Nacho Garcia's solution look promising. However, the former isn't working for me and the latter doesn't reset the values. – DLuciferin Feb 19 '16 at 03:47
  • @DLuciferin I believe it's quite simple to limit the number of lines showing at a time, but that is still a considerable range to traverse and probably not ideal. Only thing I can think of would be to have the number evaluated once a 2nd digit is entered, but I'm not sure how this is best done or how well it would work – Calvin P. Feb 19 '16 at 03:54
  • @CalvinP. I'll keep that method in mind, but the immediate flaw of single digits being passed on freely comes to mind, i.e. if I specify (40,80), it might also accept (1,9). Thank you once again for your thoughts though. – DLuciferin Feb 19 '16 at 21:52
  • Whoever voted -1 to the question, please explain why you found this unhelpful. I'm looking for the best answer. – DLuciferin Feb 20 '16 at 21:42
  • This answer can solve your problem. Use [this](https://stackoverflow.com/a/45695392/6667580) edit text input filter. – Taras Smakula Aug 15 '17 at 15:08

3 Answers3

2

Use a Textwatcher, Here I have one edittext and I am allowing a user if he enter a number in the range of 1-24

public class MainActivity extends AppCompatActivity {
EditText et;
    int num1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et= (EditText) findViewById(R.id.edit_text);
        et.addTextChangedListener(textWatcher);

    }
    TextWatcher textWatcher =new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            if(et.getText().length()>0) {
                int num = Integer.parseInt(et.getText().toString());
                if (num>=1 && num<=24)
                {
                    //save the number
                    num1=num;
                }
                else{
                    Toast.makeText(MainActivity.this,"Please enter the code in the range of 1-24",Toast.LENGTH_SHORT).show();
                    et.setText("");
                    num1=-1;
                }
            }
            }

        @Override
        public void afterTextChanged(Editable s) {

        }
    };
}

Here is the xml file

 <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/edit_text"
        android:inputType="number"
        />

At the end dont forgot to check that

if(num1==-1)
{
Toast.makeText(MainActivity.this,"Please fill all the fields",Toast.LENGTH_SHORT).show();
}
Mayur_Thakur
  • 651
  • 8
  • 15
  • Thanks for taking your time to write up your solution. I'm testing it right now for each of the cases and it will take me a bit to get back to you. However, I was wondering -- the code for the "Please fill all the fields"... where does that go? Would it go in the code space for a button listener if I were looking to press a button to receive the data and go to another activity? – DLuciferin Feb 19 '16 at 22:28
  • 1
    I've tested this and it does not work. It has the same problem as what I have encountered with previous solutions -- it takes in 1 digit and refuses to store it so I can make a larger number for more than 1 digit. For example, the range 80-200 does not work with your implementation. – DLuciferin Feb 19 '16 at 22:49
1

You can try with afterTextChanged callback of TextWatcher. See how I implemented it.

private TextWatcher tollTextWatcher = 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) {

        }

        @Override
        public void afterTextChanged(Editable editable) {

            if (editable.length() > 0) {
                int val = Integer.valueOf(editable.toString());
                if (val > MAX_VALUE) {
                    edit_toll.setText("");
                    edit_toll.setError("Rs.1 - Rs.500");
                }
            }
        }
    };
Sachin Thampan
  • 893
  • 7
  • 17
0

The best answer I've found so far is based on the solution at the following link, but it has one shortcoming: (https://stackoverflow.com/a/28743065/5906258)

The shortcoming is that once we move away from inserting our input into the EditText, the values are retained by the EditText box (instead of purged).

My (edited) code is as follows:

First class InputFilterMax:

package test;

import android.text.InputFilter;

import android.text.Spanned;
// more imports

public class InputFilterMax implements InputFilter {

private int max;
private Context context;

public InputFilterMax(Context con, int max) {
    this.max = max;
    this.context = con;
}

public InputFilterMax(Context con, String max) {
    this.max = Integer.parseInt(max);
    this.context = con;
}

@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) {
            Toast.makeText(context, "Number not accepted! Must be below or equal to " + max, Toast.LENGTH_SHORT).show();
            return null; 
        }           
        return "";
    }
}

And second class OnFocusChangeListenerMin:

package test;

import android.text.TextUtils;
import android.view.View;
import android.view.View.OnFocusChangeListener;
// more imports

public class OnFocusChangeListenerMin implements OnFocusChangeListener {

private int min;
private Context context;

public OnFocusChangeListenerMin(Context con, int min) {
    this.min = min;
    this.context = con;
}

public OnFocusChangeListenerMin(Context con, String min) {
    this.min = Integer.parseInt(min);
    this.context = con;
}


@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){
                Toast.makeText(context, "Number not accepted! Must be above or equal to " + min, Toast.LENGTH_SHORT).show();
            }

        }
    }
}
}

Then in the Activity I use the following to apply the filter and listener:

timeEdit = (EditText)findViewById(R.id.query_time_frame);
timeEdit.setFilters(new InputFilter[]{new InputFilterMax(getApplicationContext(), 24)});        // max limit on time
timeEdit.setOnFocusChangeListener(new OnFocusChangeListenerMin(getApplicationContext(), 1));    // min limit on time

If anyone can help me fix the last problem I'm having, it would be greatly appreciated.

Community
  • 1
  • 1
DLuciferin
  • 71
  • 2
  • 7