How to databind to onTextChanged for an EditText on Android?
Actually it works out of the box. I think my mistake was using an old version of the data binding framework. Using the latest, this is the procedure:
View:
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/username"
android:text="Enter username:"
android:onTextChanged="@{data.onTextChanged}" />
Model:
public void onTextChanged(CharSequence s, int start, int before, int count) {
Log.w("tag", "onTextChanged " + s);
}
Make also sure that you have assigned model into DataBinding
For ex. in your activity
lateinit var activityMainDataBinding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
val dataViewModel = ViewModelProvider(this).get(DataViewModel::class.java)
activityMainDataBinding.dataModel = dataViewModel
}
Make sure you are referncing gradle build tools v1.5.0 or higher and have enabled databinding with android.dataBinding.enabled true
in your build.gradle.
edit: Functioning demo project here. view. model.
To extend @Nilzors answer, it is also possible to pass text and/or other parameters in the layout:
View:
<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
}
You always need to pass either zero or all parameters.
The Easy Way
If you are using onTextChange()
to update text in the model then you can use Two-way Binding directly.
<data>
<variable
name="user"
type="com.package.User"/>
</data>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@={user.name}"/>
The model class will have a getter
and setter
:
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Now the name
in the model will be changed in realtime with user interaction. So using binding.getUser().getName()
will get the latest text.
One-Way Binding will only gets updated when model value is changed. It does not update model back real time.
android:text="@{user.name}"
Two-Way Binding update model variable in real time with user input.
android:text="@={user.name}"
The ONLY difference is of =
(equal sign) receives data changes to the property and listen to user updates at the same time.
If you just need text
parameter after text has changed, you could use android:afterTextChanged
binding adapter. for example:
android:afterTextChanged="@{(text) -> viewModel.onTextChange(text)}"
Then in your ViewModel
just implement like this:
fun onTextChange(editable: Editable?) {
Log.d("TAG","New text: ${editable.toString()}")
}
Furthermore, there is android:beforeTextChanged
which used to know old text before text change event, usage is same as android:afterTextChanged
.
Im using this method to handle on text change listener in android databinding.1st in your ViewModel class create LiveData variable, And also create getText method which returns LiveData object.
public MutableLiveData<String> verifyCodes = new MutableLiveData<>();
public LiveData<String> getCodes(){ return verifyCodes; }
Then in your xml files editText field set attribute on text bind with above liveData field
<EditText android:id="@+id/et_verification1st" android:layout_width="match_parent" android:layout_height="match_parent" android:text="@={viewModel.verifyCodes}"/>
In databinding you already know how to create variable of viewModel class inside data tag i beleive.As example
<data> <variable name="viewModel" type="viewModel.VerifyUserActivityViewModel" /> </data>
Ok now your activity you have to observe liveData object we created inside viewModel class
mViewModel.getCodes().observe(this,new Observer< String>(){ @Override public void onChange(String strings){ log.d("OnChange",strings); }});
You can perform any logic when text changing inside onChange method