EditText multilínea con etiqueta de acción de SoftInput Done en 2.3

82

¿Hay alguna forma de tener una multilínea EditTextpresente y usar la etiqueta de acción IME "Listo" en Android 2.3?

En Android 2.2 esto no es un problema, el botón Enter muestra la etiqueta de acción IME "Listo" ( android:imeActionLabel="actionDone") y descarta la entrada suave cuando se hace clic.

Al configurar una EditTextmultilínea, Android 2.3 elimina la capacidad de mostrar la acción "Listo" para el teclado de entrada suave.

Me las arreglé para alterar el comportamiento del botón Enter Soft Input usando a KeyListener, sin embargo, el botón Enter todavía parece una tecla enter.


Aquí está la declaración del EditText

<EditText
        android:id="@+id/Comment"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="0dp"
        android:lines="3"
        android:maxLines="3"
        android:minLines="3"
        android:maxLength="60"
        android:scrollHorizontally="false"
        android:hint="hint"
        android:gravity="top|left"
        android:textColor="#888"
        android:textSize="14dp"
        />
<!-- android:inputType="text" will kill the multiline on 2.3! -->
<!-- android:imeOptions="actionDone" switches to a "t9" like soft input -->

Cuando verifico el inputTypevalor después de cargar la configuración de la vista de contenido en la actividad, aparece como:

inputType = 0x20001

Cual es:

  • clase = TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_NORMAL
  • banderas = InputType.TYPE_TEXT_FLAG_MULTI_LINE
ohhorob
fuente

Respuestas:

163

Bueno, después de volver a leer los documentos TextViewy EditorInfo, quedó claro que la plataforma forzará IME_FLAG_NO_ENTER_ACTIONlas vistas de texto de varias líneas.

Tenga en cuenta que TextViewestablecerá automáticamente esta marca en las vistas de texto de varias líneas.

Mi solución es subclasificar EditTexty ajustar las opciones de IME después de dejar que la plataforma las configure:

@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
    InputConnection connection = super.onCreateInputConnection(outAttrs);
    int imeActions = outAttrs.imeOptions&EditorInfo.IME_MASK_ACTION;
    if ((imeActions&EditorInfo.IME_ACTION_DONE) != 0) {
        // clear the existing action
        outAttrs.imeOptions ^= imeActions;
        // set the DONE action
        outAttrs.imeOptions |= EditorInfo.IME_ACTION_DONE;
    }
    if ((outAttrs.imeOptions&EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
        outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
    }
    return connection;
}

En lo anterior, también estoy forzando IME_ACTION_DONE, aunque eso se puede lograr mediante una tediosa configuración de diseño.

ohhorob
fuente
24
Por lo general, no doy comentarios genéricos como 'Dios mío, gracias', pero esta respuesta fue lo suficientemente útil y poco apreciada como para pensar que merecía un reconocimiento. En resumen, Dios mío, gracias. :-)
plowman
3
+1 para la respuesta, pero si configura un tipo de entrada de un texto de edición desde el código en este caso. Elimina el desplazamiento vertical y agrega desplazamiento horizontal. Para resolver ese problema, utilice el siguiente código. editTextObj.setInputType (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_MULTI_LINE); Generalmente, puede suceder si está reutilizando una vista al incluir la misma en varios diseños. @ohhorob muchas gracias por la solución.
Jayshil Dave
2
¡Funciona a las mil maravillas! Pero realmente no entiendo el código. ¿Tiene algún lugar donde pueda leer sobre todo el mecanismo de la bandera?
vanleeuwenbram
Gracias, soy un principiante, puse esto en mi actividad que usa un cuadro de diálogo EditText, por lo que no está en mi xml de actividad. He intentado poner este código en mi actividad, pero da un error: The method onCreateInputConnection(EditorInfo) of type SMSMain must override or implement a supertype method. Llamas superal principio, así que no estoy seguro de cuál es el problema. ¿Tienes alguna sugerencia? Gracias.
Azurespot
@NoniA. tienes que hacer una subclase de EditText. y en esa clase tienes que llamar a este método. cree una clase que se extienda a EditText. y poner ese método en esa clase.
Shah
103

La respuesta de Ohhorob es básicamente correcta, ¡pero su código es realmente redundante! Básicamente es equivalente a esta versión mucho más simple (código completo para lectores perezosos):

package com.example.views;

import android.content.Context;
import android.util.AttributeSet;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.widget.EditText;

// An EditText that lets you use actions ("Done", "Go", etc.) on multi-line edits.
public class ActionEditText extends EditText
{
    public ActionEditText(Context context)
    {
        super(context);
    }

    public ActionEditText(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    public ActionEditText(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs)
    {
        InputConnection conn = super.onCreateInputConnection(outAttrs);
        outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
        return conn;
    }
}

Tenga en cuenta que algunas inputTypeopciones, como textShortMessagehacer que esto no funcione. Te sugiero que comiences con inputType="text". Así es como puede usarlo en su XML.

<com.example.views.ActionEditText
    android:id=...
    android:layout_stuff=...
    android:imeOptions="actionDone"
    android:inputType="textAutoCorrect|textCapSentences|textMultiLine"
    android:maxLines="3" />
Timmmm
fuente
Timmmm, ¿está probado en 2.3?
ohhorob
1
Si su código funciona en 2.3, también debería funcionar el mío. Son casi iguales, y basé el mío o el tuyo, ¡así que gracias! ¿Hay idiosincrasias de 2.3 que no están en 4.0? El estándar "sin acciones en ediciones de varias líneas" es un comportamiento deliberado agregado por Google.
Timmmm
5
Probé esto en 2.3 (y 4.x), y funcionó para mi aplicación.
mlc
2
@ matej.smitala Sí, no puedes tener ambos.
Timmmm
1
Después de horas de buscar la mejor solución, esta parece la mejor y más sencilla forma de lograr un texto de edición de varias líneas sin la tecla Intro.
micnguyen
56

Una solución alternativa a la subclasificación de la clase EditText es configurar su instancia de EditText con esto:

editText.setHorizontallyScrolling(false);
editText.setMaxLines(Integer.MAX_VALUE);

Al menos, esto me funciona en Android 4.0. Configura la instancia de EditText para que el usuario edite una cadena de una sola línea que se muestra con ajuste suave en varias líneas, incluso si se establece una acción IME.

Futzilogik
fuente
2
@Futzilogik: ¡Usted, señor, se merece muchos más votos a favor! Esta respuesta fue un salvavidas, y también simple. Quiero decir, Dios mío, wow. Ojalá pudiera votar a favor más de una vez. ¡Muchas gracias!
Swayam
3
Estoy ejecutando 4.4.2, y esto no funcionó para mí o al menos para mi forma de hacerlo. Lo hice solo en XML, así que quizás eso sea un problema. Configuré inputType en "textEmailAddress | textMultiLine", scrollHorizontally en false, maxLines en 500 (archivo xml), singleLine en false e imeOptions en actionNext. Intenté eliminar "textMultiLine" del inputtype. Con textMultiLine, obtengo la tecla ENTER en el teclado, y sin ella, todo permanece en una sola línea y aún se desplaza horizontalmente. Esta parecía la solución más fácil, pero la de arriba funciona para mí, así que adelante por ahora.
núcleo reactivo
6
Con respecto a mi comentario anterior (no puedo editarlo), sospechando que era un problema al no configurar MAX_VALUE o simplemente cambiarlos después de que se creó el texto de edición, lo intenté en el código como se indica aquí, ¡y funciona! Solo quería publicar para otros, no puedes hacerlo en XML (o yo no podría de todos modos). Otras configuraciones que tengo: singleLine = false, imeOptions = actionNext, inputType = textEmailAddress (no multiline).
núcleo reactivo
funciona muy bien. ¡Este es un buen ejemplo de cómo mejorar una respuesta anterior!
nPn
Trabajando para mí en un Galaxy S5 con Lollipop. Gran solucion Es extraño que la configuración de desplazamiento horizontal en xml no tenga el mismo efecto
Scott Birksted
7

Siguiendo la respuesta anterior

public class MultiLineText extends EditText {

    public MultiLineText(Context context) {
        super(context);
    }

    public MultiLineText(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    public MultiLineText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        InputConnection connection = super.onCreateInputConnection(outAttrs);
        int imeActions = outAttrs.imeOptions&EditorInfo.IME_MASK_ACTION;
        if ((imeActions&EditorInfo.IME_ACTION_DONE) != 0) {
            // clear the existing action
            outAttrs.imeOptions ^= imeActions;
            // set the DONE action
            outAttrs.imeOptions |= EditorInfo.IME_ACTION_DONE;
        }
        if ((outAttrs.imeOptions&EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
            outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
        }
        return connection;
    }
}

Usa esto como

<myapp.commun.MultiLineText
  android:id="@+id/textNotes"
  android:layout_height="wrap_content"
  android:minHeight="100dp"
  android:layout_width="wrap_content"
  android:hint="Notes"
  android:textSize="20sp"
  android:padding="7dp"
  android:maxLines="4"/> 
usuario3525689
fuente
5

para poner la acción Hecho, puede usar:

XML

android:inputType="text|textCapSentences"    

JAVA

editText.setHorizontallyScrolling(false);
editText.setMaxLines(Integer.MAX_VALUE);

Espero que funcione para ti.

Alex Zaraos
fuente
1

Aparentemente, la respuesta a la pregunta original es Sí, pero creo que el equipo de Android está tratando de hacer que los desarrolladores piensen un poco sobre cómo usan EditText multilínea. Quieren que la tecla Intro agregue nuevas líneas y probablemente esperan que proporciones un botón u otro medio de entrada para generar el evento que terminaste de editar.

Tengo el mismo problema y mi solución obvia fue simplemente agregar un botón de hecho y dejar que el botón de entrar agregue las nuevas líneas.

Mullins
fuente
Lo siento, puede que no haya sido lo suficientemente claro con mi pregunta ... las líneas múltiples son para ajustar una entrada de una sola línea. es decir, no se permiten caracteres de nueva línea.
ohhorob
@Mullins: ¿Agregó su propio botón "listo" en el teclado SoftInput? ¿Cómo hiciste eso mientras mantienes "Enter"?
alex.veprik
¡No! Creé un botón de hecho en la interfaz de usuario separado del teclado.
Mullins
1
Bueno, tal vez el equipo de Android debería seguir sus propios consejos y hacer que el botón de acción del TextEdit multilínea en la aplicación de mensajería cree nuevas líneas en lugar de enviar el mensaje.
Timmmm
0

Utilice estos atributos en su XML.

android: inputType = "textImeMultiLine"

android: imeOptions = "actionDone"

Gaurav
fuente