13

I have a EditText field, variable name valueInputField.

I listen to the text input change, what I want to achieve is during inputting, when the input format DOESN'T matches a regular expression, I would like to stop showing more inputs, but keep the field focused & user is able to type on keyboard still just that no real effect will take to the field.

@OnTextChanged(R.id.value_input)
protected void onTextChanged(CharSequence charSequence) {
   String inputChars = charSequence.toString().trim();
   // if doesn't match regular expression, stop showing more inputs
   if (!inputChars.matches(MY_REGEXP)) {
      // this doesn't achieve what I need.
      valueInputField.setInputType(0)
   }
}

I tried above way, it doesn't work. How to achieve what I need?

Bertram Gilfoyle
  • 9,899
  • 6
  • 42
  • 67
Leem
  • 17,220
  • 36
  • 109
  • 159

6 Answers6

3

maybe you should try below logic

maxLength=inputChars.length
if (!inputChars.matches(MY_REGEXP)) {
editText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLength)});
}

above program will set a max length of EditText when it does not match regexp.

manan5439
  • 898
  • 9
  • 24
2

You have to add an InputFilter to your textView:

here's an example:

editText.filters = arrayOf(object: InputFilter {
   override fun filter(source: CharSequence?, start: Int, end: Int, dest: Spanned?, dstart: Int, dend: Int): CharSequence {
      if (Regex("[0-9]*").matches(source!!)) {
         return source
      } else {
         return source.subSequence(start, end-1)
      }
   }
})

This filter method gets called everytime the input in the editText is being invoked. You can return the source when it matches a regex, otherwise, you can return a subSequence of the source, without the last char inserted.

The code example is in Kotlin, the translation shouldn't give you any problem :)

Luca Nicoletti
  • 2,265
  • 2
  • 18
  • 32
2

You are already doing setInputType(InputType.TYPE_NULL). But it should be used with withsetEnabled(false) to get it worked.

This will change the background color too. It is highly recommended because it gives the user a clue that it won't accept input. However you can change it as setBackgroundColor(Color.TRANSPARENT) if you wish.

If you want to hide the cursor, add setCursorVisible(false).

Alternatively you can use afterTextChanged instead of onTextChanged so that you will be able to manipulate the text.

Bertram Gilfoyle
  • 9,899
  • 6
  • 42
  • 67
1

Disabling the input type for edit text does not work properly when its focussed or being edited. Once you set the inout type to null, the view will start to receive the keypress callback methods. So, have class variable to validate the field and cancel the keys pressed. Here sample code goes.

public class SplashActivity extends AppCompatActivity{

    EditText valueInputField;
    private  boolean allowValueField2Edit = true;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ....

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

                String inputChars = charSequence.toString().trim();
                // if doesn't match regular expression, stop showing more inputs
                if (!inputChars.matches(MY_REGEXP)) {

                    // this doesn't achieve what I need.
                    valueInputField.setInputType(InputType.null);
                    allowValueField2Edit = false;
                }

            }

            @Override
            public void afterTextChanged(Editable editable) {
            }
        });

      //Once you set the input type to none fore edit control, on Key lister will receive callbacks
        valueInputField.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View view, int i, KeyEvent keyEvent) {
             //Here, you can add your custom logic to have key actions.
            //retrun false will have key effect, return true 
                return !allowValueField2Edit;
            }
        });

Hope this helps...

IntelliJ Amiya
  • 74,896
  • 15
  • 165
  • 198
Sai Prasad
  • 286
  • 1
  • 2
  • 13
  • this will not work for soft keyboard https://stackoverflow.com/questions/3697063/android-why-is-my-onkeylistener-not-called – user1506104 Jun 20 '18 at 08:16
  • 1
    On key listener will work once you make edit text field input type to null or disabled. I agree it does not work in editing mode. – Sai Prasad Jun 20 '18 at 09:02
1

If you want to stop suggestions in edit text you should try something like:

editText.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);

And to enable again after any condition use this:

editText.setInputType(InputType. TYPE_CLASS_TEXT);

Here is an example with input with a threshold of size, here should work with your regex too:

editText.addTextChangedListener(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(s.length()< threshold){
                editText.setInputType(InputType. TYPE_CLASS_TEXT);
            }
            if(s.length()>= threshold){
                editText.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
            }
        }

        @Override
        public void afterTextChanged(Editable s) {

        }
    });
Paraskevas Ntsounos
  • 1,755
  • 2
  • 18
  • 34
0

Pseudocode:

  1. wait for the input text to match your pattern
  2. when match is found, setup filter
  3. filter will need to return the same previous string on every key press

Source code:

editText.addTextChangedListener(new TextWatcher() {
    ...
    @Override
    public void afterTextChanged(Editable editable) {
        String text = editable.toString();

        // STEP 1
        if(text.matches(myRegex) && !flag) {

            // make sure that this code block is executed only once
            flag = true;

            // STEP 2
            // when match is found, always return the same string
            // therefore disabling further editing of the editText field
            editText.setFilters(new InputFilter[]{
                new InputFilter() {
                    @Override
                    public CharSequence filter(CharSequence charSequence, int i, int i1, 
                            Spanned spanned, int i2, int i3) {
                        // STEP 3
                        return spanned.subSequence(i2, i3);
                    }
                }
            });
        }
    }
});

When setting input filter, please take note of the proper way to do it. Please check this SO answer by Steven Byle.

user1506104
  • 6,554
  • 4
  • 71
  • 89
  • I run this code, but the keyboard delete button looses its effect. User is not able to delete input. – Leem Jun 21 '18 at 14:05
  • I thought you said "disable EditText inputs". If no, then setting maxlength on match should work. – user1506104 Jun 21 '18 at 14:34