7

I get EditText's text and its length in onTextChanged() method of TextWatcher.
It works fine when I type to add characters, but while removing characters from text getText() gives empty even if text is not empty. This occurs randomly and not everytime I remove characters. I have observed this happens mostly when 3-4 characters are there in text and I press backspace.

Strange part is that this issue occurs only on device, not on emulator.

Layout file :

<LinearLayout
    style="@style/create_trip_activity_components_style"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="30dp"
    android:gravity="center_vertical"
    android:orientation="horizontal" >

    <EditText
        android:id="@+id/from_location"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="5dp"
        android:ems="10"
        android:hint="@string/from_location_hint"
        android:inputType="text" >

        <requestFocus />
    </EditText>

    <Button
        android:id="@+id/use_current_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:onClick="useCurrentLocation"
        android:text="@string/use_current"
        android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>

Code :

fromLocation.addTextChangedListener(new TextWatcher() {
    @Override
    public void afterTextChanged(Editable s) {

    }

    @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 (fromLocation == null) {
            Log.d(TAG, "fromLocation is null................");
        }

        Log.d(TAG, "fromLocation text : "
                    + fromLocation.getText().toString());
        Log.d(TAG, "fromLocation text length :  "
                    + fromLocation.getText().length());
        Log.d(TAG, "S : "
                    + s);
        Log.d(TAG, "S length :  "
                    + s.length());
    }
});

Note : I tried using afterTextChanged() and beforeTextChanged() methods. But that did not solve the issue.

Geek
  • 8,280
  • 17
  • 73
  • 137
  • Editable is a CharSequence so no need to convert it to String to call length(). Just sayin. Try logging out afterTextChanged(Editable s). – Yaroslav Mytkalyk Aug 01 '13 at 12:40
  • @DoctororDrive Tried in `afterTextChanged()`. Still same problem. – Geek Aug 01 '13 at 12:49
  • can show how you remove character? – Tofeeq Ahmad Aug 01 '13 at 12:50
  • @Sameer Using soft keyboard's key. – Geek Aug 01 '13 at 12:50
  • @Akash please check my answer below and let me know if its not helping you. – Shreyash Mahajan Aug 09 '13 at 10:18
  • You're problem in firmware. I have same problem. And only updating firmware help me. It happens usually on devices with beta version OS 2.1,4.0,3.0 etc. –  Aug 09 '13 at 12:58
  • @PANDA I was waiting for a person who has faced the same problem. Can you tell me the solution or any work around? – Geek Aug 09 '13 at 14:09
  • can you post the code for this method 'editTextValueChanged(fromLocation);' – Peshal Aug 10 '13 at 18:20
  • @Akash i see you make many posts around you're problem with EditText's. Update firmware on you're phone\tablet & you can see the result. Sometimes, producer when release new phone\tablet don't adaptate him to lower versions SDK or vice versa. My problem was in Assistant tablet(2.3.3). I have problems even Activity lifecycle:) When i update him to 2.3.6 problems is gone. –  Aug 12 '13 at 06:47
  • I face the same issue on Nexus i9250 – Egor Lakomkin Aug 30 '13 at 13:48
  • @EgorLakomkin You can try updating android version. My device does not support any updates. Thus, I could not check it. – Geek Aug 30 '13 at 17:15

10 Answers10

1

I don't see any problem. The text of from_location should change and it does.

Why are you "checking" the EditText (from_location) while you are inside the TextWatcher code. I don't think that the value of the EditText has to be "stable" while is changing.

Maybe what happens is that when you check the CharSequence in from_location is being updated and, sometimes, you catch it just in the middle of a change, sometimes after.

Did you check if the (CharSequence s, int start, int before, int count) are returning the expected values?

As I see this situation. If you want to do any changes on the text you should do them on the String s argument of the afterTextChanged method.

I wrote this code to check what is happening while changing the content of the EditText, maybe it is of any

    mEdtText.addTextChangedListener(new TextWatcher() {
        private static final String TAG = "TextWatcher";
        private static final boolean DEBUG = true;

        @Override
        public void onTextChanged(CharSequence s, int start, int before,
                int count) {
            if (DEBUG)
                Log.d(TAG,
                        "(onTextChanged) In \"" + s + "\" " + before
                                + " characters "
                                + " are being replaced at " + start
                                + " by " + count + " ("
                                + s.subSequence(start, start + count) + ")");
            if (DEBUG)
                Log.d(TAG,
                        "(onTextChanged) mEdtText: \"" + mEdtText.getText()
                                + "\"");
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {
            if (DEBUG)
                Log.d(TAG,
                        "(beforeTextChanged) In \"" + s + "\" " + count
                                + " characters ("
                                + s.subSequence(start, start + count)
                                + ") are about to be replaced at " + start
                                + " by " + after);
            if (DEBUG)
                Log.d(TAG,
                        "(beforeTextChanged) mEdtText: \""
                                + mEdtText.getText() + "\"");

        }
    }

If you check the source code of EditText you can see that inherit the getText method from TextView and it returns the CharSequence mText. You can seed that another CharSequence mTransformed is defined too. And that in the huge setText method there is a moment where mText is replaced by mTransformed. Probably when you call from_location's getText you are getting mText and the second time you do it after setText kicked in and you get mTransformedas answer.

If you want to check this just change

CharSequence cs = from_location.getText();
Log.d(... + cs + ...); // no need to call toString as implicit call.
...
Log.d(... + cs.length() + ...);
Asincrono
  • 417
  • 6
  • 12
  • So to solve the issue of getting `mText`, which can be empty at a particular point in time as you said, what should I do? – Geek Aug 10 '13 at 05:16
  • BTW I tried logging `CharSequence s` and it was returning same value as my EditText. Moreover, I tried to get text in `afterTextChanged()` method which should work if the issue is getting text when it is being replaced. But it still gave empty text. Even I face same issue in `beforeTextChanged()` method. – Geek Aug 10 '13 at 05:20
  • So, if I understand it reight. When deleting some charaters of a word you previously wrote in the `EditText`, the methods: `beforeTextChanged`, `onTextChanged` and `afterTextChanged` return an empty `CharSequence`/`Editable` when they shoudn't? For example. if you have the word "Hello" and you start deleting, what happens? You get an empty sequence after deleting two or three chars while you should get "Hel", "He", etc. – Asincrono Aug 10 '13 at 08:44
  • Yes, you got it correct. I have some texts and start deleting them. Then at some point even when few characters are remaining in EditText I get "". – Geek Aug 10 '13 at 09:30
  • So you get an `EditText` with some characters on your screen while it's `getText` returns and empty `CharSequence`? Is this "stable", I mean, after you get the empty text, it keeps returning empty or only happens inside the `TextWatcher`'s code? Btw, which version of android and device are you testing? and, Can you test the code in any other device (other than the virtual machine)? I'm trying to replicate your results without success whatsoever... – Asincrono Aug 10 '13 at 10:04
  • Yes, EditText has characters when it returns empty. But when I delete next character it starts giving correct value. So once or twice while deleting whole sentence it gives empty. On emulator, I am not facing any issue but on device. Device runs on 4.1.1. Project min SDK is 14 and target SDK is 17. Unfortunately, I have only one device. So I have not tested on any other device. – Geek Aug 11 '13 at 07:37
  • I can not reproduce your problem, and I tried it in a couple of devices. The only idea I have left is that the software keyboard installed on that device is doing something strange (sort of autocompletion?). I would try with other keyboard app to discard that possibility. And to avoid any other thing that could mess things I would try the `EditText` behabiour with an activity dedicated only to that task (no idea if you are already doing this). Sorry I can't be of more help. – Asincrono Aug 15 '13 at 12:22
0

If you were going through the debug mode, have in mind that it has two places where it stores values. In my case EditText had mText (Spannable String Builder) and it's sub field (also mText) is the one with ID. The spannable string builder will return value of .toString(). The other one will return value of .getText().

Dino Velić
  • 888
  • 11
  • 24
0

Try using the CharSequence s from the onTextChange() should be the same as the one returned by fromLocation.getText().

Hadriel
  • 159
  • 1
  • 13
0
public void afterTextChanged(Editable s) {
           if(s.length()>=6)
           {

           }
           else{

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

          }
0

This might be what you need. This is some code I used on a project to search through strings. I have a method called mySearchMethod, dont worry about that. But I get my edit text string on the method after text changed..

 public void search(){
    // Notice I used a final edittext
    final EditText editText = (EditText) findViewById(R.id.search);


    // create the TextWatcher
    TextWatcher textWatcher = new TextWatcher() {

        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void afterTextChanged(Editable editable) {


              String searchQuery = editText.getText().toString();

              // This method is just something I did with the string I got
              MySearchMethod(searchQuery);




        }
    };

    //we must add the textWatcher to our EditText
    editText.addTextChangedListener(textWatcher);

}

Call the method search() in your on create to initialize it.

NightSkyCode
  • 1,141
  • 2
  • 16
  • 33
0

What is fromLocation ? You should use CharSequence s like below.

Try this......

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

// if(fromLocation == null) {
//         Log.e(TAG, "fromLocation is null.");
//  }

Log.e(TAG, "fromLocation text : " + s.toString());
Log.e(TAG, "fromLocation text length :  " + s.toString().length()); 

// Log.e(TAG, "fromLocation id : " + fromLocation.getId());
// Log.e(TAG, "fromLocation text : " + fromLocation.getText().toString());
// Log.e(TAG, "fromLocation text length :  " +    //fromLocation.getText().toString().length());            
}
sandy
  • 3,311
  • 4
  • 36
  • 47
0

Try This It'll Work...

final EditText from_location = (EditText) findViewById(R.id.from_location);

    from_location.addTextChangedListener(new TextWatcher()
    {
        @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(from_location == null) {
                Log.v("", "fromLocation is null.");
        }

        Log.v("", "fromLocation id : " + from_location.getId());
        Log.v("", "fromLocation text : " + from_location.getText().toString());
        Log.v("", "fromLocation text length :  " + from_location.getText().toString().length());            

        }
    });
Hariharan
  • 24,741
  • 6
  • 50
  • 54
0

I am updating other Second EditText value based on the user input on First EditText and visa-versa.

So, for First EditText i have added TextWatche like below which never get crashed and never fall in to any error or exception. You can try some thing like that.

final EditText from_location = (EditText) findViewById(R.id.from_location);

 from_location.addTextChangedListener(new TextWatcher() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            if(!(from_location.getText().toString().equals(""))) {
                Log.e(TAG, "fromLocation id : " + fromLocation.getId());
                Log.e(TAG, "fromLocation text : " + fromLocation.getText().toString());
                Log.e(TAG, "fromLocation text length :  " + fromLocation.getText().toString().length());
            }else{
                 Log.e(TAG, "fromLocation is null.");
            }
        }

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

        }
    });

Hope this will surly help you. Please let me know if nits not helping you.

Enjoy Coding.... :)

Shreyash Mahajan
  • 23,386
  • 35
  • 116
  • 188
0

Alright Here is the solution, instead of getting the text using getText, just convert the charSequence passed to the

onTextChanged(CharSequence s, int start, int before,
                    int count)

callback using s.toString()

My sample class looks like this

package com.peshal.texttest;

import android.app.Activity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.widget.EditText;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    EditText  fromLocation = (EditText) findViewById(R.id.editText1);
    fromLocation.addTextChangedListener(new TextWatcher(){

        @Override
        public void afterTextChanged(Editable arg0) {
            // 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) {
        Log.d("Current String is :" ,s.toString());

        }

      });
  }


 }
Peshal
  • 1,508
  • 1
  • 12
  • 22
  • 1
    My code, if you see, has already `Log.d(TAG, "S : " + s);`. Do you think doing `s.toString()` will make any difference now? – Geek Aug 11 '13 at 07:39
0

i did have the same problem. My code ran fine on most devices, but on the Motorola Razr i with Android 4.1.2 it randomly returned an empty string.

I did the following workaround:

// TextWatcher Methods
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3)
{
}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3)
{
    fromLocation.post(new Runnable()
    {

        @Override
        public void run()
        {
            Editable text = fromLocation.getText();
            //... now the string is not empty anymore
        }
    });

}

@Override
public void afterTextChanged(Editable editable)
{
}

Although i didn't know why the problem occured - posting it in a Runnable (possibly delayed) fixed it. And didn't affect the behaviour on the other devices.

In your case you probably have to do some extra != null checks for fromLocation - in my case its never null.

Simon Meyer
  • 1,946
  • 12
  • 23