Android Data Binding - Observe edit text's value that is wrapped in custom view
If you want to use the xml syntax in your example (app:password="@=controller.password"
), then you need to define static methods for 2-way data binding with @BindingAdapter
and @InverseBindingAdapter
annotations. You can find an official sample here (though I prefer using top-level kotlin extension functions rather than nesting them in an object
since it doesn't require the @JvmStatic
annotation and feels more idiomatic). You can also check out the library source for how 2-way binding adapters are defined for TextView
here, though it's probably more involved than what you'd need to do for your case.
If all you need to do is observe text changes and you don't need to set the text directly on your custom view, then 2-way data binding is unnecessary and you can set some sort of listener that will call back when the text changes (which could be set via data binding if you have a public setter) or expose a LiveData<String>
that you can observe (not using xml/data binding).
I can think of 2 ways of doing this
- Using Binding Adapter: You can pass your viewModel instance to your binding adapter. In your binding adapter you would observe editText changes and call any of the viewModel's public methods, something like this:
@BindingAdapter("bind:doSomething") fun bindDoSomething( view: EditText, vm: ViewModel? ) { vm?.let { view.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { } override fun afterTextChanged(s: Editable?) { } override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { vm.callFun() } }) } }
and in your xml:
app:doSomething="@{vm}"
- Using Traditional Interface Approach: Having an interface between your custom view class and your activity/fragment. The interface method can be called from onTextChanged of TextChangedListener implemented in your custom view class.
Let me know if this helps or if you have any questions