6

I have an EditText with a TextWatcher. It is supposed to format the text to a human height like 5'9". But when user makes a mistake and wants to delete the mistyped character the TextWather doesn't allow him to do that. Let's say user wants to delete " characther the TextWather adds its back right away. Below is the code. So how do I allow user to delete text in the EditText?

private class CustomTextWatcher implements TextWatcher {
    private EditText mEditText;

public CustomTextWatcher(EditText e) {
    mEditText = e;
}

public void beforeTextChanged(CharSequence s, int start, int count,
        int after) {
}

public void onTextChanged(CharSequence s, int start, int before,
        int count) {


}

public void afterTextChanged(Editable s) {
    int count = s.length();
    String str = s.toString();
    if (count == 1) {
        str = str + "'";
    } else if (count == 3) {
        str = str + "\"";
    } else if ((count > 4) && (str.charAt(str.length() - 1) != '\"')) {
        str = str.substring(0, str.length() - 2)
                + str.charAt(str.length() - 1) + "\"";
    } else {
        return;
    }
    mEditText.setText(str);
    mEditText.setSelection(mEditText.getText().length());


}

}

Sean Kilb
  • 959
  • 5
  • 16
  • 27

2 Answers2

8

Ignoring the fact Karakuri posted about your code being in the wrong callback, you could add a simple fix where you just listen to what key the user uses.

Without any real testing or further improvements to your existing code, this does seem to fix your described problem:

package com.example.testwatchertest;

import android.app.Activity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnKeyListener;
import android.widget.EditText;

public class MainActivity extends Activity implements TextWatcher {

    EditText editText;
    boolean keyDel = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        editText = (EditText) findViewById(R.id.editText);
        editText.addTextChangedListener(this);

        editText.setOnKeyListener(new OnKeyListener() {

            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {

                if (keyCode == KeyEvent.KEYCODE_DEL){
                    keyDel = true;
                }else{
                    keyDel = false;
                }
                return false;
            }
        });

    }

    @Override
    public void afterTextChanged(Editable s) {
        // TODO Auto-generated method stub

    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

        if (!keyDel) {

            String str = s.toString();
            if (count == 1) {
                str = str + "'";
            } else if (count == 3) {
                str = str + "\"";
            } else if ((count > 4) && (str.charAt(str.length() - 1) != '\"')) {
                str = str.substring(0, str.length() - 2) + str.charAt(str.length() - 1) + "\"";
            } else {
                return;
            }
            editText.setText(str);
            editText.setSelection(editText.getText().length());

        }

    }

}
Stefan de Bruijn
  • 6,289
  • 2
  • 23
  • 31
  • Thank you Stefan. It fixed the issue. I have moved the code to the afterTextChanged() methods and I used boolean to check the key status. It worked. Thank you again. – Sean Kilb Dec 28 '12 at 16:39
  • For some reason the TextWatcher doesn't work when user tries to type after he has fixed the mistake? I mean when mistyped a character and then erases it and then tries to type again the TextWatcher is not adding ' and " symbols. How can I fix that? – Sean Kilb Dec 28 '12 at 18:59
  • 1
    The OnKeyListener doesn't work on Samsung Galaxy but works fine on Motorola Xoom. – Sean Kilb Dec 31 '12 at 16:00
  • If I press other than DELETE key, it wouldnt call OnKeyListener.Please advise. – Umesh May 28 '14 at 09:22
2

From the docs:

public abstract void onTextChanged(CharSequence s, int start, int before, int count)

This method is called to notify you that, within s, the count characters beginning at start have just replaced old text that had length before. It is an error to attempt to make changes to s from this callback.

You should make any changes in afterTextChanged(), not in either of the other two callbacks.

public abstract void afterTextChanged(Editable s)

This method is called to notify you that, somewhere within s, the text has been changed. It is legitimate to make further changes to s from this callback, but be careful not to get yourself into an infinite loop, because any changes you make will cause this method to be called again recursively. (You are not told where the change took place because other afterTextChanged() methods may already have made other changes and invalidated the offsets. But if you need to know here, you can use setSpan(Object, int, int, int) in onTextChanged(CharSequence, int, int, int) to mark your place and then look up from here where the span ended up.)

Karakuri
  • 38,365
  • 12
  • 84
  • 104
  • I moved the code to the afterTextChanged() method and that didn't make any difference. I have updated my post. Thanks. – Sean Kilb Dec 28 '12 at 16:20