Как привязать данные к onTextChanged для EditText на Android?
В Yigit Boyar и George Mount рассказывают о привязке данных к Android, они иллюстрируют, как легко привязываться к TextWatcher
onTextChanged
(при 13: 41). На кнопке. Ошибочны ли их слайды? Прежде всего Button
View не имеет свойства onTextChanged
. Он не имеет метода setOnTextChanged
. Также не существует EditText
. Но они оба имеют addTextChangedListener
, который принимает вход TextWatcher
.
Так о чем они говорят? Как они это делают? Их примерный код не компилируется, но дает эту ошибку:
Error:(17) No resource identifier found for attribute 'onTextChanged' in package 'android'
Как мне привязываться к "событию с измененным текстом" на любом представлении или в частности в EditText с помощью платформы привязки данных Android?
Ответы
Ответ 1
На самом деле это работает из коробки. Я думаю, что моя ошибка заключалась в использовании старой версии структуры привязки данных. Используя последнее, это процедура:
Вид:
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/username"
android:text="Enter username:"
android:onTextChanged="@{data.onTextChanged}" />
Модель:
public void onTextChanged(CharSequence s, int start, int before, int count) {
Log.w("tag", "onTextChanged " + s);
}
Убедитесь, что вы ссылаетесь на gradle инструменты сборки v1.5.0 или новее и включили привязку данных с помощью android.dataBinding.enabled true
в файле build.gradle.
изменить: Функциональный демонстрационный проект здесь. просмотреть. model.
Ответ 2
Чтобы расширить ответ @Nilzors, также возможно передать текст и/или другие параметры в макете:
Вид:
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/username"
android:text="Enter username:"
android:onTextChanged="@{(text, start, before, count) -> viewModel.onUsernameTextChanged(text)}" />
ViewModel:
public void onUsernameTextChanged(CharSequence text) {
// TODO do something with text
}
Вам всегда нужно передать либо нулевой, либо все параметры.
Ответ 3
Легко
Если вы используете onTextChange()
для обновления текста в модели, вы можете напрямую использовать двустороннюю привязку.
<data>
<variable
name="user"
type="com.package.User"/>
</data>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@={user.name}"/>
И у вашего модельного класса будет getter
и setter
.
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Теперь имя в модели будет изменено в реальном времени при взаимодействии с пользователем. Поэтому, всякий раз, когда вы используете binding.getUser().getName()
, вы получите последний текст.
Односторонняя привязка будет обновляться только при изменении значения модели. Он не обновляет модель в режиме реального времени.
android:text="@{user.name}"
Двухстороннее связывание обновляет переменную модели в режиме реального времени с помощью пользовательского ввода.
android:text="@={user.name}"
ЕДИНСТВЕННАЯ разница - =
(знак равенства) в одностороннем и двустороннем связывании.
Ответ 4
лучший способ для этого - добавить адаптер связывания и средство просмотра текста.
public class Model{
private TextWatcher textWatcher;
public Model(){
this.textWatcher= getTextWatcherIns();
}
private TextWatcher getTextWatcherIns() {
return new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
//do some thing
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//do some thing
}
@Override
public void afterTextChanged(Editable s) {
//do some thing
}
};
}
public TextWatcher getTextWatcher() {
return textWatcher;
}
public void setTextWatcher(TextWatcher textWatcher) {
this.textWatcher = textWatcher;
}
@BindingAdapter("textChangedListener")
public static void bindTextWatcher(EditText editText, TextWatcher textWatcher) {
editText.addTextChangedListener(textWatcher);
}
}
и в вашем XML добавить этот атрибут к вашему тексту редактирования
<EditText
android:id="@+id/et"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:textChangedListener="@{model.textWatcher}" />
Ответ 5
Прикрепите setOnFocusChangeListener
к EditText
и сравните текстовое содержимое с глобальной переменной (предыдущего состояния/содержимого поля), чтобы определить, изменилось ли оно:
mEditTextTitle.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(!hasFocus)
// check if text has changed
}
});
Ответ 6
Код не должен запускаться. Согласно документам API, ни TextView, ни EditText не имеют атрибута XML onTextChanged. Они поддерживают метод addTextChangedListener, но я не уверен, как это работает с привязкой данных.
https://developer.android.com/reference/android/widget/TextView.html
https://developer.android.com/reference/android/widget/EditText.html