Как избежать бесконечного цикла
Пытаюсь написать динамический конвертер величин (Inch/km) т.е. хочу чтобы между полями editText и editText2 была связь и значения менялись в реальном времени без нажатия лишних кнопок.
Написал обработку через TextWatcher, но там очевидно процесс зацикливается потому что поля заменяют сами себя и в итоге устройство виснет.
Я чувствую, что проблема детская, но буду благодарен если вы подскажите как избежать зацикливания и мб подкинете какие нибудь ресурсы (желательно сразу по Kotlin) почитать. Спасибо.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
editText.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(p0: Editable?) {
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
try {
editText2.setText("${editText.text.toString().toFloat() / 39370}")
status.text = ""
} catch (e: Exception) {
status.text = "error" }
}
})
editText2.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(p0: Editable?) {
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
try {
editText.setText("${editText2.text.toString().toFloat() * 39370}")
status.text = ""
} catch (e: Exception) {
status.text = "error"}
}
})
}
Ответы (2 шт):
Предлагаю такой вариант на Java (Ещё не знаком с Kotlin)
final EditText txt1 = findViewById(R.id.txt1);
final EditText txt2 = findViewById(R.id.txt2);
final TextWatcher txt1W = 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) {
txt2.setText(txt1.getText());
}
};
final TextWatcher txt2W = 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) {
txt1.setText(txt2.getText());
}
};
txt1.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
if (hasFocus) {
txt1.addTextChangedListener(txt1W);
} else {
txt1.removeTextChangedListener(txt1W);
}
}
});
txt2.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
if (hasFocus) {
txt2.addTextChangedListener(txt2W);
} else {
txt2.removeTextChangedListener(txt2W);
}
}
});
Простыми словами можно дополнительно прослушивать фокусировку и в зависимости от этого добавлять и удалять прослушку изменений текста.
Решил проблему через установку фокуса. Получается тело под полем ввода запускается только когда мы его касаемся и игнорирует изменения своего состояния пока его не трогают.
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
var v:View = currentFocus
if (v == editText) {
b = true
try {
f = editText.text.toString().toFloat()
status.text = ""
} catch (e:Exception) {b = false}
if (b) {
f = f / 39370; editText2.setText(f.toString(),TextView.BufferType.EDITABLE) } else
status.text = "error"
}
}
