Reputation: 333
I have two TextViews EditText
and have assigned each on a TextChangedListener, which reference each other, changing the text of the other textview. Specifically:
rateText.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(!rateText.getText().toString().equals("")) {
float price = Float.parseFloat(priceText.getText().toString());
float rate = Float.parseFloat(rateText.getText().toString());
// REFERNCES THE OTHER TEXT
amountText.setText(Float.toString(price / rate));
} else {
amountText.setText("");
}
}
});
amountText.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(!rateText.getText().toString().equals("")) {
float price = Float.parseFloat(priceText.getText().toString());
float amount = Float.parseFloat(amountText.getText().toString());
// REFERNCES THE OTHER TEXT
rateText.setText(Float.toString(price / amount));
} else {
rateText.setText("");
}
}
});
This results in an infinite loop, because each listener causes the other one to trigger. How can i prevent this without needing a button or something?
Upvotes: 0
Views: 1414
Reputation: 634
You could hold the TextWatchers in fields and use a static method to set the text "silently" without notifying the listeners like this:
private TextWatcher rateWatcher; //hold watchers in fields
private TextWatcher amountWatcher;
//...
void yourMethodOrCallback() { //whatever
//...
amountWatcher = 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 (!rateText.getText().toString().equals("")) {
float price = Float.parseFloat(priceText.getText().toString());
float amount = Float.parseFloat(amountText.getText().toString());
// REFERNCES THE OTHER TEXT
setTextSilently(amountText, amountWatcher, Float.toString(price / amount));
} else {
setTextSilently(rateText, rateWatcher, "");
}
}
};
rateWatcher = 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 (!rateText.getText().toString().equals("")) {
float price = Float.parseFloat(priceText.getText().toString());
float rate = Float.parseFloat(rateText.getText().toString());
// REFERNCES THE OTHER TEXT
setTextSilently(amountText, amountWatcher, Float.toString(price / rate));
} else {
setTextSilently(amountText, amountWatcher, "");
}
}
};
rateText.addTextChangedListener(rateWatcher);
amountText.addTextChangedListener(amountWatcher);
}
private static void setTextSilently(EditText editText, TextWatcher textWatcher, CharSequence text) {
editText.removeTextChangedListener(textWatcher); //removing watcher temporarily
editText.setText(text); //setting text
editText.addTextChangedListener(textWatcher); //readding watcher
}
Upvotes: 1
Reputation: 21
I would agree with @Lotharyx's suggestion to try using a boolean first. The boolean variable should only have to be final if declared in the same scope as the method where you are adding these TextWatchers, otherwise you can use an instance variable (doesn't have to be static).
Another thing you could try is to remove the TextWatcher before the body of code in afterTextChanged(), and add it again after you have call setText() on the other EditText. But this would also require you to make the TextWatcher objects instance variables or declare them as final.
@Override
public void afterTextChanged(Editable s) {
rateText.removeTextChangedListener(rateTextListener);
if(!rateText.getText().toString().equals("")) {
float price = Float.parseFloat(priceText.getText().toString());
float amount = Float.parseFloat(amountText.getText().toString());
// REFERNCES THE OTHER TEXT
rateText.setText(Float.toString(price / amount));
} else {
rateText.setText("");
}
rateText.addTextChangedListener(rateTextListener);
}
Upvotes: 0