Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TextWatcher onTextChanged not working with soft keyboard auto-complete / suggested words

I'm Implementing a TextWatcher on an EditText to find and underline a series of keywords within the text whenever a new character is entered by the user. However when a suggested / auto-complete word on the soft keyboard is selected, instead of adding the suggested word to the Edittext and then calling the onTextChanged function the half complete word is deleted. I found this rather strange as entering individual characters activates the onTextChanged function just fine. Any help would be greatly appreciated.

PS. if anyone knows a better way to process an EditText on the fly please let me know.

Code:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_codify_test);
    final EditText editText = (EditText) findViewById(R.id.editText_codifyTest);
    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 (!checked) { //stop infinite loop
                checked = true;
                cursorPosition = editText.getSelectionStart(); //get cursor position before text modification
                codifyText(editText);
            } else {
                checked = false;
            }
        }
        @Override
        public void afterTextChanged(Editable s) {
        }
    });
}

//Find and underline keywords
private void codifyText(EditText editText) {
    String plainText = editText.getText().toString() + " ";
    int prevWhiteSpace = 0;
    final Context context = this;
    SpannableString codifiedText = new SpannableString(plainText.substring(0, plainText.length() - 1));
    if (codifiedText.length() == 0) return;

    for (int i = 0; i < plainText.length(); i ++){
        if (Character.isWhitespace(plainText.charAt(i))){
            String currWord = plainText.substring(prevWhiteSpace, i);
            if (isKeyWordInDataBase(currWord)) {
                ClickableSpan clickableSpan = new ClickableSpan() {
                    @Override
                    public void onClick(View view) {

                    }
                };
            codifiedText.setSpan(clickableSpan, prevWhiteSpace, i, 0);
            }
            prevWhiteSpace = i + 1;
        }
    }
    editText.setMovementMethod(LinkMovementMethod.getInstance());
    editText.setText(codifiedText, TextView.BufferType.SPANNABLE);
    editText.setSelection(cursorPosition); //set cursor to position prior to edit
}
like image 344
mysteryhobo Avatar asked Jan 02 '16 12:01

mysteryhobo


1 Answers

Its better to go for afterTextChanged method.
In the following sample, the entered text is retrieved and handled using a Handler for the further process

    EditText text1;
    StringBuffer previousChar=new StringBuffer();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.activity_main);
    text1=(EditText)findViewById(R.id.editText);
    text1.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) {
                }
                @Override
                public void afterTextChanged(Editable s) {
                    if(!previousChar.toString().equals(s.toString())){
                        Message msg=new Message();
                        msg.obj=s.toString();
                        localHandler.sendMessage(msg);
                        previousChar=new StringBuffer(s.toString());
                        Log.i("TAG", "TextEntered = "+s);
                    }
                }
            });}

And in the handler

private Handler localHandler = new Handler(){
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            String value=(String)msg.obj;
            //Your logic with the text entered that is retrieved 
        }
    };
like image 130
Sreehari Avatar answered Oct 19 '22 00:10

Sreehari