Texto de Editline multilínea con el botón de acción Hecho

¿Es posible tener un widget EditText con android:inputType="textMultiLine" establecido, y android:imeOptions="actionDone" al mismo tiempo?

Me gustaría un cuadro de edición multilínea, con el botón de acción en el teclado para Listo, no Intro (Retorno de carro), pero parece que no funciona.

Gracias por adelantado

Utilizar

 editText.setImeOptions(EditorInfo.IME_ACTION_DONE); editText.setRawInputType(InputType.TYPE_CLASS_TEXT); 

y en XML:

 android:inputType="textMultiLine" 

De la documentación de android: ‘ “textMultiLine” Teclado de texto normal que permite a los usuarios ingresar largas cadenas de texto que incluyen saltos de línea (retornos de carro) . ‘Por lo tanto, el atributo textMultiLine no es apropiado si desea tener el botón’ Listo ‘en el teclado.

Una forma simple de obtener un campo de entrada multilínea (en este caso 3 líneas) con el botón listo es usar EditText con

 android:lines="3" android:scrollHorizontally="false" 

Sin embargo, por alguna razón, esto solo funciona para mí si hago estas configuraciones en el código en lugar del archivo de diseño (en onCreate) por

 TextView tv = (TextView)findViewById(R.id.editText); if (tv != null) { tv.setHorizontallyScrolling(false); tv.setLines(3); } 

Espero que esto ayude a alguien, ya que tardó bastante tiempo en descubrirlo. Si encuentra una forma de hacerlo funcionar desde el manifiesto, háganoslo saber.

Ejemplo de trabajo! Cree la clase de EditText personalizada que admite esta característica y use la clase en el archivo xml. Código de trabajo:

 package com.example; import android.content.Context; import android.util.AttributeSet; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.widget.EditText; 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; } }  

Creo que esta es la manera de hacerte una cosa. Tener android:inputType="textMultiLine" , android:imeOptions="actionDone" hace que ingresar la funcionalidad de la clave sea ambiguo. Solo ten en cuenta que puedes usar android:lines="10" y tal vez eliminar android:inputType="textMultiLine" , pero depende de lo que quieras lograr a veces solo necesitas el android:inputType="textMultiLine" y no hay reemplazo para ello.

 EditText ed=new EditText(this); ed.setOnKeyListener(new OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if(keyCode==66){ //do your stuff here } return false; } }); 

Esto parece funcionar para mí a la perfección

 int lineNum = 2; mEditText.setHorizontallyScrolling(false); mEditText.setLines(3); 

Respuesta corta: No, creo que no es posible antes de API nivel 11 (3.0).

El mismo problema surgió aquí (discutido en los comentarios a la respuesta aceptada):

Botón de acción de teclado suave de Android

Del comentario final:

Al mirar algunas aplicaciones en mi teléfono, parece común tener el cuadro multilínea al último, con un botón visible “Hecho” o “Enviar” debajo de él (por ejemplo, la aplicación de correo electrónico).

Si no se trata del aspecto del teclado en pantalla, simplemente podría colocar un oyente de entrada en el teclado y disparar el estado “listo” si el usuario ingresa una nueva línea.

si utiliza la opción de entrada textImeMultiline con imeoptions flagnext y actionnext obtendrá un botón siguiente en lugar del retorno de carro

Estoy en 4.x y traté de llamar a setHorizontallyScrolling () (con o sin setLine () o setMaxLines ()), así como muchas configuraciones XML diferentes para mostrar el botón Hecho. Ninguno de ellos funcionó. La conclusión es que si EditText es multilínea, Android siempre querrá mostrar el retorno de carro en lugar del botón “Listo”, a menos que haya algún truco al respecto.

La solución de menor complejidad que encontré que no implica reasignar el comportamiento del retorno de carro está aquí: https://stackoverflow.com/a/12570003/3268329 . Esta solución anulará el insaciable deseo de Android de forzar la configuración del indicador IME_FLAG_NO_ENTER_ACTION para las vistas de varias líneas, lo que hace que el botón Hecho desaparezca.

Una forma simple de evitar esta situación:

  • mantén estos atributos en EditText:

     android:inputType="textMultiLine" android:scrollHorizontally="false" 
  • luego agregue este código para ocultar el teclado solo cuando se presione ENTER:

     editText.setOnEditorActionListener(new OnEditorActionListener() { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) { editText.setSelection(0); InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(editText.getWindowToken(), 0); return true; } else { return false; } } }); 

Luché también durante bastante tiempo, ¡pero finalmente encontré una solución!

Simplemente cree una clase personalizada EditText como tal:

 public class EditTextImeMultiline extends EditText { public void init() { addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { for (int i = s.length(); i > 0; i--) if (s.subSequence(i - 1, i).toString().equals("\n")) s.replace(i - 1, i, ""); } }); setSingleLine(); setHorizontallyScrolling(false); this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { EditTextImeMultiline.this.setLines(EditTextImeMultiline.this.getLineCount()); } }); } public EditTextImeMultiline(Context context) { super(context); init(); } public EditTextImeMultiline(Context context, AttributeSet attrs) { super(context, attrs); init(); } public EditTextImeMultiline(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public EditTextImeMultiline(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(); } } 

Esta clase elimina lineBreaks (\ n), ajusta el texto como lo haría textMultiline, Y le permite reemplazar el botón Enter por una ImeAction;).

Solo necesita llamarlo en su XML en lugar de la clásica clase EditText.

Para explicar la lógica aquí:

  • Establezca EditText como una sola línea para poder mostrar un botón ImeAction en lugar de Enter.
  • Elimine el desplazamiento horizontal para que el texto pase a la siguiente línea cuando llegue al final de la vista.
  • Observe cómo cambia el diseño con onglobalLayoutListener y establezca su parámetro de “línea” en “lineCount” del texto actual que contiene el editText. Esto es lo que refresca su altura.

La solución de trabajo está aquí, cree su EditTextView personalizado (simplemente extienda una vista de texto) y anule OnInputConnection con una porción de código que encontrará en la respuesta aceptada aquí: Texto Edit de Multiline con Etiqueta de Acción de SoftInput Listo en 2.3

Si bien ninguna de las otras soluciones alguna vez funcionó para mí, las siguientes funcionaron maravillosamente y me ahorraron días y días de búsqueda en Google, con algunos giros propios por supuesto. Lamentablemente, no recuerdo dónde obtuve exactamente el código y, por lo tanto, no puedo darle al autor el crédito que él / ella merece.

En tu código de Java:

 ////////////Code to Hide SoftKeyboard on Enter (DONE) Press/////////////// editText.setRawInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); editText.setImeActionLabel("DONE",EditorInfo.IME_ACTION_DONE); //Set Return Carriage as "DONE" editText.setImeOptions(EditorInfo.IME_ACTION_DONE); editText.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (event == null) { if (actionId == EditorInfo.IME_ACTION_DONE) { // Capture soft enters in a singleLine EditText that is the last EditText // This one is useful for the new list case, when there are no existing ListItems editText.clearFocus(); InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0); } else if (actionId == EditorInfo.IME_ACTION_NEXT) { // Capture soft enters in other singleLine EditTexts } else if (actionId == EditorInfo.IME_ACTION_GO) { } else { // Let the system handle all other null KeyEvents return false; } } else if (actionId == EditorInfo.IME_NULL) { // Capture most soft enters in multi-line EditTexts and all hard enters; // They supply a zero actionId and a valid keyEvent rather than // a non-zero actionId and a null event like the previous cases. if (event.getAction() == KeyEvent.ACTION_DOWN) { // We capture the event when the key is first pressed. } else { // We consume the event when the key is released. return true; } } else { // We let the system handle it when the listener is triggered by something that // wasn't an enter. return false; } return true; } });