¿Cómo manejo el clic hecho en el botón de ImeOptions?

185

Tengo un lugar EditTextdonde configuro la siguiente propiedad para que pueda mostrar el botón Listo en el teclado cuando el usuario hace clic en Editar texto.

editText.setImeOptions(EditorInfo.IME_ACTION_DONE);

Cuando el usuario hace clic en el botón Listo en el teclado de la pantalla (terminado de escribir), quiero cambiar un RadioButtonestado.

¿Cómo puedo rastrear el botón hecho cuando se presiona desde el teclado de la pantalla?

Captura de pantalla que muestra el botón 'listo' en la parte inferior derecha del teclado del software

d-man
fuente
1
puede ser OnKeyboardActionListener ayudarme con algún ejemplo de código ??
d-man el

Respuestas:

210

Terminé con una combinación de respuestas de Roberts y Chirags:

((EditText)findViewById(R.id.search_field)).setOnEditorActionListener(
        new EditText.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        // Identifier of the action. This will be either the identifier you supplied,
        // or EditorInfo.IME_NULL if being called due to the enter key being pressed.
        if (actionId == EditorInfo.IME_ACTION_SEARCH
                || actionId == EditorInfo.IME_ACTION_DONE
                || event.getAction() == KeyEvent.ACTION_DOWN
                && event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
            onSearchAction(v);
            return true;
        }
        // Return true if you have consumed the action, else false.
        return false;
    }
});

Actualización: el código anterior algunas veces activaría la devolución de llamada dos veces. En su lugar, opté por el siguiente código, que obtuve de los clientes de chat de Google:

public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
    // If triggered by an enter key, this is the event; otherwise, this is null.
    if (event != null) {
        // if shift key is down, then we want to insert the '\n' char in the TextView;
        // otherwise, the default action is to send the message.
        if (!event.isShiftPressed()) {
            if (isPreparedForSending()) {
                confirmSendMessageIfNeeded();
            }
            return true;
        }
        return false;
    }

    if (isPreparedForSending()) {
        confirmSendMessageIfNeeded();
    }
    return true;
}
Thomas Ahle
fuente
44
Solo busqué IME_ACTION_DONE y me sorprendió que no se activara. Después de que también busqué ACTION_DOWN y KEYCODE_ENTER, finalmente se activó onEditorAction (). Como no veo ninguna diferencia en el teclado incorporado (esperaba que se resaltara la tecla Intro), me pregunto cuál es el punto de usar android: imeOptions = "actionSend" para el diseño EditText XML.
Alguien en algún lugar
¿Por qué no se acepta esta respuesta? ¿esto falla en algunos casos?
Archie.bpgc
1
developer.android.com/reference/android/widget/… (Descripción de lo que un "evento" es lo mismo.)
Darpan
2
La segunda solución también se activa dos veces.
Bagusflyer
1
¿Qué es isPreparedForSending()y por qué regresa el segundo método true?
CoolMind
122

Pruebe esto, debería funcionar para lo que necesita:


editText.setOnEditorActionListener(new EditText.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
    if (actionId == EditorInfo.IME_ACTION_DONE) {
       //do here your stuff f
       return true;
    }
    return false;
    } 
});
chikka.anddev
fuente
10
Esto no funciona para HTC Evo. Por lo que he podido entender, HTC implementó su propio teclado virtual que ignora las imeOptions.
Dan
Esto es suficiente (no es necesario mirar la acción del evento o el código clave, como en la respuesta aceptada); funciona en mis dispositivos de prueba Nexus y Samsung.
Jonik
solo para estar seguro, asegúrese de que la acción en el código y la vista coincida <EditText android:imeOptions="actionDone" android:inputType="text"/>
bh_earth0
40
<EditText android:imeOptions="actionDone"
          android:inputType="text"/>

El código de Java es:

edittext.setOnEditorActionListener(new OnEditorActionListener() { 
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (actionId == EditorInfo.IME_ACTION_DONE) {
            Log.i(TAG,"Here you can write the code");
            return true;
        }    
        return false;
    }
});
Vinoj Vetha
fuente
Debería volver verdadero en la cláusula if para decir que lo ha manejado
Tim Kist
26

Sé que esta pregunta es antigua, pero quiero señalar lo que funcionó para mí.

Intenté usar el código de muestra del sitio web de desarrolladores de Android (que se muestra a continuación), pero no funcionó. Así que verifiqué la clase EditorInfo y me di cuenta de que el valor entero IME_ACTION_SEND se especificaba como 0x00000004.

Código de muestra de desarrolladores de Android:

editTextEmail = (EditText) findViewById(R.id.editTextEmail);
editTextEmail
        .setOnEditorActionListener(new OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId,
                    KeyEvent event) {
                boolean handled = false;
                if (actionId == EditorInfo.IME_ACTION_SEND) {
                    /* handle action here */
                    handled = true;
                }
                return handled;
            }
        });

Entonces, agregué el valor entero a mi res/values/integers.xmlarchivo.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="send">0x00000004</integer>
</resources>

Luego, edité mi archivo de diseño de la res/layouts/activity_home.xmlsiguiente manera

<EditText android:id="@+id/editTextEmail"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:imeActionId="@integer/send"
  android:imeActionLabel="@+string/send_label"
  android:imeOptions="actionSend"
  android:inputType="textEmailAddress"/>

Y luego, el código de muestra funcionó.

iRuth
fuente
17

Más detalles sobre cómo configurar OnKeyListener y hacer que escuche el botón Listo.

Primero agregue OnKeyListener a la sección de implementos de su clase. Luego agregue la función definida en la interfaz OnKeyListener:

/*
 * Respond to soft keyboard events, look for the DONE press on the password field.
 */
public boolean onKey(View v, int keyCode, KeyEvent event)
{
    if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
        (keyCode == KeyEvent.KEYCODE_ENTER))
    {
        // Done pressed!  Do something here.
    }
    // Returning false allows other listeners to react to the press.
    return false;
}

Dado un objeto EditText:

EditText textField = (EditText)findViewById(R.id.MyEditText);
textField.setOnKeyListener(this);
Robert Hawkey
fuente
2
Esto ya no funciona en aplicaciones que se dirigen al nivel 17+ de la API, porque su OnKeyListener ya no se activa para eventos de teclas programables: developer.android.com/reference/android/text/method/…
jjb
¿Sugieren una alternativa ahora?
Robert Hawkey
2
He cambiado a usar setOnEditorActionListener para buscar EditorInfo.IME_ACTION_DONE, que parece funcionar bien.
jjb
onKey debería devolver verdadero, no falso.
ralphgabb
16

Si bien la mayoría de las personas ha respondido la pregunta directamente, quería dar más detalles sobre el concepto detrás de ella. Primero, me llamó la atención de IME cuando creé una actividad de inicio de sesión predeterminada. Me generó un código que incluía lo siguiente:

<EditText
  android:id="@+id/password"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:hint="@string/prompt_password"
  android:imeActionId="@+id/login"
  android:imeActionLabel="@string/action_sign_in_short"
  android:imeOptions="actionUnspecified"
  android:inputType="textPassword"
  android:maxLines="1"
  android:singleLine="true"/>

Ya debería estar familiarizado con el atributo inputType. Esto solo informa a Android el tipo de texto esperado, como una dirección de correo electrónico, contraseña o número de teléfono. La lista completa de valores posibles se puede encontrar aquí .

Sin embargo, era el atributo imeOptions="actionUnspecified"que no entendía su propósito. Android le permite interactuar con el teclado que aparece desde la parte inferior de la pantalla cuando se selecciona texto usando InputMethodManager. En la esquina inferior del teclado, hay un botón, por lo general dice "Siguiente" o "Listo", según el campo de texto actual. Android te permite personalizar esto usando android:imeOptions. Puede especificar un botón "Enviar" o un botón "Siguiente". La lista completa se puede encontrar aquí .

Con eso, puede escuchar las pulsaciones en el botón de acción definiendo un TextView.OnEditorActionListenerpara el EditTextelemento. Como en tu ejemplo:

editText.setOnEditorActionListener(new EditText.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(EditText v, int actionId, KeyEvent event) {
    if (actionId == EditorInfo.IME_ACTION_DONE) {
       //do here your stuff f
       return true;
    }
    return false;
    } 
});

Ahora en mi ejemplo tenía android:imeOptions="actionUnspecified"atributo. Esto es útil cuando desea intentar iniciar sesión en un usuario cuando presiona la tecla Intro. En su Actividad, puede detectar esta etiqueta y luego intentar iniciar sesión:

    mPasswordView = (EditText) findViewById(R.id.password);
    mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
        @Override
        public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
            if (id == R.id.login || id == EditorInfo.IME_NULL) {
                attemptLogin();
                return true;
            }
            return false;
        }
    });
Donato
fuente
6

Gracias a chikka.anddev y Alex Cohn en Kotlin es:

text.setOnEditorActionListener { v, actionId, event ->
    if (actionId == EditorInfo.IME_ACTION_DONE ||
        event?.action == KeyEvent.ACTION_DOWN && event.keyCode == KeyEvent.KEYCODE_ENTER) {
        doSomething()
        true
    } else {
        false
    }
}

Aquí verifico la Enterclave, porque regresa en EditorInfo.IME_NULLlugar de IME_ACTION_DONE.

Consulte también Android imeOptions = "actionDone" no funciona . Añadir android:singleLine="true"en el EditText.

CoolMind
fuente
6

Solución Kotlin

La forma básica de manejarlo en Kotlin es:

edittext.setOnEditorActionListener { _, actionId, _ ->
    if (actionId == EditorInfo.IME_ACTION_DONE) {
        callback.invoke()
        true
    }
    false
}

Extensión Kotlin

Use esto para simplemente llamar edittext.onDone{/*action*/}a su código principal. Hace que su código sea mucho más legible y fácil de mantener

fun EditText.onDone(callback: () -> Unit) {
    setOnEditorActionListener { _, actionId, _ ->
        if (actionId == EditorInfo.IME_ACTION_DONE) {
            callback.invoke()
            true
        }
        false
    }
}

No olvides agregar estas opciones a tu texto de edición

<EditText ...
    android:imeOptions="actionDone"
    android:inputType="text"/>

Si necesita inputType="textMultiLine"ayuda, lea esta publicación

Gibolt
fuente
1
Gran respuesta, gracias por compartir! Sin setOnEditorActionListenerembargo, parece que sigo recibiendo una advertencia de pelusa con respecto al valor de retorno del . Tal vez es sólo una cuestión de ajustes de configuración locales, pero mi linter realmente, realmente quiere que añada una elserama demasiado para poder aceptar el "verdadero" como una declaración de retorno del oyente (en contraposición a la if-bloque).
dbm
0

Si usa Anotaciones de Android https://github.com/androidannotations/androidannotations

Puedes usar la anotación @EditorAction

@EditorAction(R.id.your_component_id)
void onDoneAction(EditText view, int actionId){
    if(actionId == EditorInfo.IME_ACTION_DONE){
        //Todo: Do your work or call a method
    }
}
Rafael Rocha
fuente