Kotlin - проверяет, было ли содержимое edittext изменено пользователем или программно

У меня 2 editTexts. При изменении editText1 содержимое editText2 будет равно editText1 * 5. Когда editText2 изменено, содержимое editText1 будет равно editText2 * 5.

Теперь, если я использую addTextChangedListener(), он зацикливается, потому что содержимое editTexts всегда будет меняться, вызывая сбой. Мне нужно определить, изменяются ли editTexts пользователем или программно.

Любая идея?

Если можете, вот мой код:

     fun EditText.doubleValue() = text.toString().toDoubleOrNull() ?: 0.0

     editText1.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

            override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

            override fun afterTextChanged(editable: Editable) {

               editText2.setText(editText1.doubleValue() * 5)
            }
        })



editText2.addTextChangedListener(object : TextWatcher {
                override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

                override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

                override fun afterTextChanged(editable: Editable) {

                   editText1.setText(editText2.doubleValue() * 5)
                }
            })

Обновлено: РЕШЕНО

Я использовал if(editText.isFocused), чтобы проверить, был ли изменен пользователем

1
0
3 396
3

Ответы 3

Я думаю, что лучшим вариантом будет использование опции actionDone ime. Таким образом, только когда пользователь закончит редактировать поле, другой текст редактирования будет обновлен. Для этого вам нужно добавить android:imeOptions="actionDone" в ваши xml el элементы editText. Затем в вашем коде вместо того, чтобы прислушиваться к изменениям, вы должны добавить слушателя действий:

editText1.setOnEditorActionListener() { v, actionId, event ->
      if(actionId == EditorInfo.IME_ACTION_DONE){
          editText2.setText(editText1.doubleValue() * 5)
          true
      } else {
          false
      }
}

Не зная, что вы используете вариант, я не знаю, подойдет ли вам это решение. Если вам нужно обновить editTexts в реальном времени, возможно, проверка того, находится ли поле в фокусе, может предотвратить цикл бесконечности:

 editText1.addTextChangedListener(object : TextWatcher {
        override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

        override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

        override fun afterTextChanged(editable: Editable) {
           if(editText1.hasFocus()) {
             editText2.setText(editText1.doubleValue() * 5)
           }
        }
    })

Вы можете сохранить TextWatcher в переменных, удалить их перед программным изменением содержимого каждого TextView, а затем снова добавить их.

class MyActivity: AppCompatActivity() {

  private val textWatcher1 = object : TextWatcher {
    override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

    override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

    override fun afterTextChanged(editable: Editable) {
      updateEditText2()
    }
  }

  fun EditText.doubleValue() = text.toString().toDoubleOrNull() ?: 0.0

  private val textWatcher2 = object : TextWatcher {
    override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

    override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

    override fun afterTextChanged(editable: Editable) {
      updateEditText1()
    }
  }

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    editText1.addTextChangedListener(textWatcher1)
    editText2.addTextChangedListener(textWatcher2)
  }


  private fun updateEditText1() {
    editText1.removeTextChangedListener(textWatcher1)
    editText1.setText(editText2.doubleValue() * 5)
    editText1.addTextChangedListener(textWatcher1)
  }

  private fun updateEditText2() {
    editText2.removeTextChangedListener(textWatcher2)
    editText2.setText(editText1.doubleValue() * 5)
    editText2.addTextChangedListener(textWatcher2)
  }
}

Я не могу осмыслить вариант использования, но из всех представленных вариантов я думаю, что ваше решение, вероятно, самое чистое, которое не включает управление флагами.

Sam 31.10.2018 15:24

Первым делом удалите функцию doubleValue(), она не работает (или, по крайней мере, у меня не получилось заставить ее работать).
Используйте 2 логические переменные from1 и from2, указывающие, что изменение, которое будет сделано, происходит из кода, и проверьте их значения в наблюдателях.
Скажите, что вы печатаете внутри editText1.
Средство просмотра текста editText1 перед изменением значения editText2 устанавливает from1 = true.
Когда текст editText2 изменяется, средство просмотра текста editText2 проверяет значение from1 и, поскольку это true, ничего не делает, только устанавливает from1 = false.

var from1 = false;
var from2 = false;

editText1.addTextChangedListener(object : TextWatcher {
    override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

    override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

    override fun afterTextChanged(editable: Editable) {
        if (from2) {
            from2 = false
        } else {
            val value = editText1.text.toString().toDoubleOrNull() ?: 0.0
            from1 = true
            editText2.setText((value * 5).toString())
        }
    }
})

editText2.addTextChangedListener(object : TextWatcher {
    override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

    override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

    override fun afterTextChanged(editable: Editable) {
        if (from1) {
            from1 = false
        } else {
            val value = editText2.text.toString().toDoubleOrNull() ?: 0.0
            from2 = true
            editText1.setText((value * 5).toString())
        }
    }
})

Другие вопросы по теме