Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

<EditText               
    android:id="@+id/preSignUpPg2EnterPhone"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"       
    onOkInSoftKeyboard="@{(v) -> viewModel.someMethod()}"
    />

onOkInSoftKeyboard doesn't exists... Is there something to create this behavior?

Thanks!

like image 914
Leandro Borges Ferreira Avatar asked Jul 24 '17 18:07

Leandro Borges Ferreira


People also ask

How do I change the Done button on my android keyboard?

First you need to set the android:imeOptions attribute equal to “actionDone” for your target EditText as seen below. That will change your 'RETURN' button in your EditText's soft keyboard to a 'DONE' button.

What is IME action?

As stated in Android Documentation, IME Action directs the keyboard what type of action should be displayed. This depends on you (the developer) to change the IME Action according to your needs. For example, a text field intended to be used as a search bar would contain the search IME Action and so on…

What is imeOptions android?

android:imeOptions="actionSend" /> You can then listen for presses on the action button by defining a TextView.OnEditorActionListener for the EditText element. In your listener, respond to the appropriate IME action ID defined in the EditorInfo class, such as IME_ACTION_SEND . For example: Kotlin Java.

How do I hide the keyboard on my android?

You can force Android to hide the virtual keyboard using the InputMethodManager, calling hideSoftInputFromWindow , passing in the token of the window containing your focused view. This will force the keyboard to be hidden in all situations. In some cases, you will want to pass in InputMethodManager.


2 Answers

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:

public class OnOkInSoftKeyboardListener {
    void onOkInSoftKeyboard();
}

Then you need a BindingAdapter:

@BindingAdapter("onOkInSoftKeyboard") // I like it to match the listener method name
public static void setOnOkInSoftKeyboardListener(TextView view,
        final OnOkInSoftKeyboardListener listener) {
    if (listener == null) {
        view.setOnEditorActionListener(null);
    } else {
        view.setOnEditorActionListener(new OnEditorActionListener() {
            @Override
            public void onEditorAction(TextView v, int actionId, KeyEvent event) {
                // ... solution to receiving event
                if (somethingOrOther) {
                    listener.onOkInSoftKeyboard();
                }
            }
        });
    }
}
like image 190
George Mount Avatar answered Oct 23 '22 05:10

George Mount


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 with method invoke did not match signature of any method 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 -> true
            else -> false
        }

        val keydownEvent = event?.keyCode == KeyEvent.KEYCODE_ENTER 
            && event.action == KeyEvent.ACTION_DOWN

        if (imeAction or keydownEvent)
            true.also { f(v.editableText.toString()) }
        else false
    }
}

MyViewModel.kt:

fun signIn(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"/>
like image 26
ersin-ertan Avatar answered Oct 23 '22 05:10

ersin-ertan