10

I have an EditText. Now I want to get all changes made by the user to this EditText and work with them before manually inserting them into the EditText. I don't want the user to directly change the text in the EditText. This should only be done by my code (e.g. by using replace() or setText()).

I searched a bit and found an interesting class named InputConnectionWrapper. According to the javadoc it shall act as a proxy for a given InputConnection. So I subclassed it like this:

private class EditTextInputConnection extends InputConnectionWrapper {

    public EditTextInputConnection(InputConnection target, boolean mutable) {
        super(target, mutable);
    }

    @Override
    public boolean commitText(CharSequence text, int newCursorPosition) {
                    // some code which takes the input and manipulates it and calls editText.getText().replace() afterwards
        return true;
    }

}

To initialize the wrapper I overwrote the following method in my EditText-subclass:

public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
    InputConnection con = super.onCreateInputConnection(outAttrs);
    EditTextInputConnection connectionWrapper = new EditTextInputConnection(con, true);
    return connectionWrapper;
}

However, commitText() never gets called. The onCreateInputConnection() gets called and the constructor of EditTextInputConnection also, but never commitText(), altough it should be, when I enter some text into the field. At least, that's how I understand the usage of InputConnectionWrapper. Or am I wrong?

Edit: It seems, that commitText() is only called for special characters like "."," " etc. As I understand the Android sourcecode for all other characters InputConnectionWrapper.sendKeyEvent() should be called, but that's not the case... I'm absolutely stuck at this point. I already tried EditText.onKeyPreIme(), but this only works on hardware keyboards. So that's no alternative... I don't really understand, why Android handles soft keyboards that different from hardware keyboards. EditText.onTextChanged() gets also fired on non-user input, so this is also not, what I'm looking for.

ubuntudroid
  • 3,680
  • 6
  • 36
  • 60

3 Answers3

7

It turned out, that the above usage of the InputConnectionWrapper was totally correct. However, commitText() gets never called (except for special cases), as there are other methods, which are used during typing. These are mainly setComposingText() and sendKeyEvent(). However, it is also important to overwrite seldom used methods like deleteSurroundingText() or commitText() to make sure to catch every user input.

ubuntudroid
  • 3,680
  • 6
  • 36
  • 60
  • 1
    This doesn't prevent user from copy-pasting random text into EditText, but works for everything else. – Alexey Oct 23 '13 at 09:40
  • @ubuntudroid Hi, do you know which methods need to be overwritten to capture all inputs? Including copy pasting. – what is sleep Dec 17 '13 at 16:51
  • @what_is_sleep As Alexey pointed out correctly, you can't capture copy-pasting with this method, sorry. Maybe ´Text Watcher´ can help you handling this case? – ubuntudroid Dec 18 '13 at 14:53
1

Use a TextWatcher, disconnect it when you're modifying your edittext and reconnect it when done. This way, you won't trigger infinite calls.

1

Blundell suggested on the chat that you use a TextWatcher. Check if this helps you out.

Community
  • 1
  • 1
Lukas Knuth
  • 25,449
  • 15
  • 83
  • 111
  • The problem with a TextWatcher is, that I cannot determine the source of input there (i.e. keyboard input or input directly from my code). It would also be notified, if I changed the text by EditText.getText().replace() or EditText.setText(), I assume. – ubuntudroid Jul 10 '11 at 08:17
  • I'm not sure, have you tested it? – Lukas Knuth Jul 10 '11 at 09:11
  • It should be like this, as getText().replace()/insert() operates directly on the Editable behind the EditText. So the TextWatcher which tracks the changes of the Editable will be notified on any change of the Editable. I'm currently working on another solution which incorporates a subclass of Editable and special methods to access it from code and overwritten methods for insert() and replace(). Will post my findings here once it's done. – ubuntudroid Jul 10 '11 at 09:44