Leem
Leem

Reputation: 18298

Disable EditText inputs while keeping it focused

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?

Upvotes: 13

Views: 937

Answers (6)

Sai Prasad
Sai Prasad

Reputation: 306

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

Upvotes: 1

Paraskevas Ntsounos
Paraskevas Ntsounos

Reputation: 1777

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

        }
    });

Upvotes: 1

user1506104
user1506104

Reputation: 7086

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.

Upvotes: 0

Bertram Gilfoyle
Bertram Gilfoyle

Reputation: 10235

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.

Upvotes: 2

manan5439
manan5439

Reputation: 958

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.

Upvotes: 3

Luca Nicoletti
Luca Nicoletti

Reputation: 2407

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

Upvotes: 2

Related Questions