Skip to content Skip to sidebar Skip to footer

Use Done Button On Keyboard In Databinding

I am trying to use the done button of the soft keyboard to activate a method via databinding. Just like onClick. Is there a way to do that? example:

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"