Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I delete text in EditText with TextWatcher? Every time it detects a string and formats its

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());


}

}

like image 599
Sean Kilb Avatar asked Dec 28 '12 15:12

Sean Kilb


People also ask

How can I change the EditText text without triggering the text watcher?

public class MyTextWatcher implements TextWatcher { private EditText editText; // Pass the EditText instance to TextWatcher by constructor public MyTextWatcher(EditText editText) { this. editText = editText; } @Override public void afterTextChanged(Editable e) { // Unregister self before update editText.

In which condition is TextWatcher used?

The TextWatcher interface can be used for listening in for changes in text in an EditText.

What is the use of TextWatcher in Android?

EditText is used for entering and modifying text. While using EditText width, we must specify its input type in inputType property of EditText which configures the keyboard according to input. EditText uses TextWatcher interface to watch change made over EditText.

What is afterTextChanged in Android?

afterTextChanged : This will call when you stop typing, it will calls after you completely wrote "sport", that is the main diffrence.


2 Answers

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());

        }

    }

}
like image 90
Stefan de Bruijn Avatar answered Oct 03 '22 16:10

Stefan de Bruijn


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

like image 34
Karakuri Avatar answered Oct 03 '22 15:10

Karakuri