user2301560
user2301560

Reputation: 33

Unable to implement textwatcher correctly in android

I was looking for a way to find out what the user was typing in an EditText and I stumbled upon the TextWatcher. Problem is I don't understand what the parameters refer to in the function. I want to keep track of the text being entered by the user letter by letter. I can't figure out which argument is the correct subscript no. I have tried different variations but haven't had any luck with those.

Essentially I want to save text entered in an array until the user presses the ','button or exceeds the limit of 24 characters. Please advise.

public class Main extends Activity implements OnClickListener {

    // inputans.setOnKeyListener(this);

    Button go;
    TextView answer;
    TextView check;
    EditText inputans, inputq;
    boolean done1 = false;
    char[] ans = new char[30];
    String predef = "Please answer my question";
    char[] predefc = predef.toCharArray();
    int len = predefc.length;
    int i = 0;
    char[] substring = new char[30];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initialisevars();
        go.setEnabled(false);
        go.setOnClickListener(this);

        inputans.addTextChangedListener(new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before,
                    int count) {

                if ((count - before) > 0) {
                    char current = s.charAt(before);                   
                    if (current == '.' || i >= 24) { // 24 check
                        // ans[i]='\0';
                        // inputans.setText(predef,
                        // TextView.BufferType.EDITABLE);
                        check.setText(predef);
                        go.setEnabled(true);
                    } else {

                        ans[i] = current;
                        i++; // char[] substring = char[30]; back button
                                // problem,check if prev length - current length
                                // >0

                        int m;
                        for (m = 0; m <= i; m++) {
                            substring[m] = predefc[m];
                        }

                        check.setText(substring.toString());
                        // substring[m]='\0';
                        /*
                         * inputans.setText(substring.toString(),
                         * TextView.BufferType.EDITABLE);
                         */

                    }
                }

            }

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

                // TODO Auto-generated method stub
            }

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

            }
        });

    }

    private void initialisevars() {
        // TODO Auto-generated method stub
        go = (Button) findViewById(R.id.bGo);
        answer = (TextView) findViewById(R.id.tvAns);
        inputans = (EditText) findViewById(R.id.etTricky);
        inputq = (EditText) findViewById(R.id.etQues);
        check = (TextView) findViewById(R.id.textView1);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        switch (v.getId()) {
        case R.id.bGo: {

            answer.setText(ans.toString()); 

        }
            break;

        }
    }

}

Upvotes: 3

Views: 1103

Answers (2)

s.d
s.d

Reputation: 29436

beforeTextChanged() is called before any change happens, here you can get the old contents, which are just going to change:

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

  String toBeChanged = s.subSequence(start,start+count).toString();

}

To get what replaced the previous contents, use onTextChanged(), this is called just as the replacement is done:

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

  String replacement = s.subSequence(start,start+count).toString();

}

If you are not interested in what is being changed and just want to know something changed, just for the purpose of to save it, or compare it, or validate it etc etc, you can use the third method afterTextChanged(). This method is to be used when you don't want to interfere with user editing one or more characters:

public void afterTextChanged(Editable s) {
  String newString = s.toString(); 
}

Upvotes: 3

Piotr Chojnacki
Piotr Chojnacki

Reputation: 6857

In Android documentation, you can read that:

public abstract void onTextChanged (CharSequence s, int start, int before, int count) Added in API level 1

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.

It means, that:

  • s is already a modified text (you can get it's length, by s.length())
  • count is number of characters that have been added
  • start is position in which new characters have been added
  • before is length of text before changes

Basically to achieve what you want, I'd rather go with this approach instead of arrays:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initialisevars();
    go.setEnabled(false);
    go.setOnClickListener(this);

    inputans.addTextChangedListener(new TextWatcher() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before,
                int count) {

            if ((s.length() - before) > 0) {  // Check if text is longer than before changing
                char current = s.charAt(before);                   
                if (current == '.' || s.length() >= 24) {
                    check.setText(predef);
                    go.setEnabled(true);
                } else {
                    check.setText(s);
                }
            }

        }

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

            // TODO Auto-generated method stub
        }

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

        }
    });
}

Simple as that.

Upvotes: 3

Related Questions