Use Done Button On Keyboard In Databinding
Solution 1:
I won't claim to be an expert in onEditorAction()
or soft keyboard. That said, assuming you use the solution to the stack overflow question Firoz Memon suggested, you can make it happen. Even if there is another solution that works better, this can give you an idea on how to add your own event handlers.
You'd need a binding adapter that takes some kind of handler. Let's assume you have an empty listener like this:
publicclassOnOkInSoftKeyboardListener {
voidonOkInSoftKeyboard();
}
Then you need a BindingAdapter:
@BindingAdapter("onOkInSoftKeyboard")// I like it to match the listener method namepublicstaticvoidsetOnOkInSoftKeyboardListener(TextView view,
final OnOkInSoftKeyboardListener listener) {
if (listener == null) {
view.setOnEditorActionListener(null);
} else {
view.setOnEditorActionListener(newOnEditorActionListener() {
@OverridepublicvoidonEditorAction(TextView v, int actionId, KeyEvent event) {
// ... solution to receiving eventif (somethingOrOther) {
listener.onOkInSoftKeyboard();
}
}
});
}
}
Solution 2:
Using Kotlin, kapt produces:
e: [kapt] An exception occurred: android.databinding.tool.util.LoggedErrorException: Found data binding errors.
****/ data binding error ****msg:Listener class kotlin.jvm.functions.Function1 withmethod invoke did notmatch signature ofanymethod viewModel::signIn
(because viewModel::signIn
is of type KFunction1
) so we can't use a method reference. However, if we create a variable within the viewModel
that is explicit about the type, then we can pass that variable as the binding's param. (or just use a class)
Bindings.kt:
@BindingAdapter("onEditorEnterAction")fun EditText.onEditorEnterAction(f: Function1<String, Unit>?) {
if (f == null) setOnEditorActionListener(null)
else setOnEditorActionListener { v, actionId, event ->
val imeAction = when (actionId) {
EditorInfo.IME_ACTION_DONE,
EditorInfo.IME_ACTION_SEND,
EditorInfo.IME_ACTION_GO -> trueelse -> false
}
val keydownEvent = event?.keyCode == KeyEvent.KEYCODE_ENTER
&& event.action == KeyEvent.ACTION_DOWN
if (imeAction or keydownEvent)
true.also { f(v.editableText.toString()) }
elsefalse
}
}
MyViewModel.kt:
funsignIn(password: String) {
Toast.makeText(context, password, Toast.LENGTH_SHORT).show()
}
val signIn: Function1<String, Unit> = this::signIn
layout.xml:
<EditText
android:id="@+id/password"
app:onEditorEnterAction="@{viewModel.signIn}"
android:imeOptions="actionDone|actionSend|actionGo"
android:singleLine="true"/>
Solution 3:
Just as i was looking at this myself, here a simpler version where the function is directly called from the data binding:
In your ViewModel use this function:
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
returnfalse; // if you want the default action of the actionNext or so onreturntrue; // if you want to intercept
}
And in the layout:
android:onEditorAction="@{(view,actionId,event) -> viewModel.onEditorAction(view,actionId,event)}"
Solution 4:
Kotlin, without writing custom binding adapter
In Layout,
<EditText...android:onEditorAction="@{(view, actionId, event) -> viewModel.onDoneClicked(view, actionId, event)}" />
ViewModel
funonDoneClicked(view: View, actionId: Int, event: KeyEvent?): Boolean {
if(actionId == EditorInfo.IME_ACTION_DONE) {
// handle herereturntrue
}
returnfalse
}
Note:event
can be null, so make KeyEvent
nullable by putting ?
there.
Solution 5:
You can directly call login method what inside ViewModel by implementing setOnEditorActionListener
to the Edittext, taking reference from binging class
loginFragmentBinding.etPassword.setOnEditorActionListener(TextView.OnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
loginViewModel.login()
return@OnEditorActionListenertrue
}
false
})
Post a Comment for "Use Done Button On Keyboard In Databinding"