Android: EditText in Dialog no abre el teclado virtual

82

Entonces tengo lo que parece ser un problema común, que es que EditText en mi cuadro de diálogo no aparece cuando se enfoca. He visto varias soluciones alternativas, como en este hilo , este y este (y muchos más), pero nunca he visto una explicación satisfactoria de por qué está sucediendo esto en primer lugar.

Preferiría que Android use su propio comportamiento predeterminado para EditTexts que para construir el mío, pero parece que todos (en esos hilos) han aceptado que el comportamiento predeterminado para EditTexts en Dialogs es simplemente dar un cursor y no un teclado. ¿Por qué sería eso?

Para que conste, ninguna de estas soluciones parece funcionar para mí; lo más cerca que he podido llegar es forzar que aparezca un teclado debajo del cuadro de diálogo (usando InputMethodManager.toggleSoftKeyboard (*)). Mi configuración particular es API15, EditText aparece en un pie de página en un ListView dentro de un AlertDialog. El Android EditText: focusable = "true" está configurado y onFocusChangeListener está recibiendo eventos de enfoque.

Editar:

Según lo solicitado, aquí está el fragmento de código específico con el que estoy trabajando. No me molestaré con el diseño completo, pero en esta aplicación específica, EditText aparece en respuesta a presionar un botón en el diálogo (similar a una vista de acción ). Está contenido en un RelativeLayout que, por defecto, tiene visibilidad "desaparecida":

 <RelativeLayout 
       android:id="@+id/relLay"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_centerVertical="true"
       android:visibility="gone"
       android:layout_marginTop="5dp"
       android:layout_marginBottom="5dp">

        <ImageButton
            android:id="@+id/cancelBut"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:background="@color/transparent"
            android:src="@drawable/cancelButton" 
            android:layout_margin="5dp"/>

        <ImageButton
            android:id="@+id/okBut"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toLeftOf="@id/cancelBut"
            android:background="@color/transparent"
            android:src="@drawable/okButton"
            android:layout_margin="5dp" />

        <EditText 
            android:id="@+id/editText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:focusable="true"
            android:layout_toLeftOf="@id/okBut"/>
   </RelativeLayout>

El código que crea esto establece la visibilidad del relativo diseño en "Visible" (y oculta los otros elementos de la interfaz de usuario). Esto debería ser suficiente para levantar el teclado cuando EditText se enfoca, según mi experiencia con EditText. Sin embargo, por alguna razón, este no es el caso. Puedo configurar el siguiente onFocusChangeListener:

    edit_text.setOnFocusChangeListener(new OnFocusChangeListener() {

            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                // For whatever reason we need to request a soft keyboard.
                    InputMethodManager imm = (InputMethodManager)dlg.getWindow().getContext().getSystemService(_Context.INPUT_METHOD_SERVICE);
                    if(hasFocus)
                        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                    Log.v("DialogProblem", "Focus requested, " + (hasFocus?"has focus.":"doesn't have focus."));
                }
            }
        });

Usando esta configuración, cuando entro por primera vez el EditText, el onFocusChangedListener se activa y genera un registro que invariablemente se ve así:

Focus requested, has focus.
Focus requested, doesn't have focus.
Focus requested, has focus.

El teclado aparece y luego desaparece, probablemente porque lo alterno dos veces, pero incluso cuando me aseguro de que permanece arriba, está detrás de la ventana de diálogo (en un área atenuada), y no hay forma de acceder a él sin cerrar el diálogo. .

Dicho esto, me gustaría hacer hincapié en que a pesar de que puede ser capaz de conseguir este trabajo en torno al trabajo, estoy principalmente interesado en la búsqueda de una simple razón por qué la EditarTexto no está activando en primer lugar, y por qué esto parece ser tan común!

Paul
fuente
¿Le importaría publicar el fragmento de código relevante (donde establece el enfoque, agrega un oyente de enfoque, etc.)?
Alexander Lucas
Puedo (y lo haré cuando vuelva a una computadora), pero creo que mi pregunta más amplia no involucra a un oyente enfocado. Me pregunto por qué parece ser un problema común que la edición de texto en un cuadro de diálogo no abra el teclado. Si bien estaría feliz de usar un kluge si esa es la forma de hacerlo, pero me gustaría saber por qué es necesario tal cosa.
Paul

Respuestas:

189

Bien, después de leer mucho, he descubierto por qué esto es un problema y no necesito usar ninguna solución alternativa.

El problema parece ser (al menos en mi caso), que dado que el lugar donde ingresa el texto está oculto inicialmente (o anidado o algo así), AlertDialog está configurando automáticamente la marca WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM (o alguna combinación de eso y WindowManager .LayoutParams.FLAG_NOT_FOCUSABLE) para que las cosas no activen la aparición de una entrada suave.

La forma que encontré para solucionar esto es agregar la siguiente línea después de que se haya creado el cuadro de diálogo:

dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);

Una vez hecho esto, EditText actúa como un EditText normal, sin necesidad de errores ni soluciones.

Paul
fuente
84
Cuando intenté borrar las banderas después de Crear, no funcionó. Funcionó solo cuando lo usé así: Dialog = builder.create (); Dialog.show (); Dialog.getWindow (). ClearFlags (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); Dialog.getWindow (). SetSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
Alex Fragotsis
1
@AlexanderFragotsis después de probar tantas soluciones diferentes en stackoverflow, ¡tu comentario es el único que funciona! ¡Gracias!
Bruce
20
SOFT_INPUT_STATE_‌ VISIBLE no funcionó para mí. Usé SOFT_INPUT_STATE_ALWAYS_VISIBLE y luego funcionó. Simplemente poniéndolo allí si alguien más tiene el mismo problema
kb_14
Sí, tampoco pude hacer que SOFT_INPUT_STATE_VISIBLE funcione, pero _ALWAYS_VISIBLE funciona. ¿Alguien sabe qué está pasando allí?
bwoogie
Muy importante hacer el clearFlags()después show(), gracias @AlexanderFragotsis
Javier Mendonça
17

Tengo el mismo problema en mi propia aplicación. Si está desarrollando para el nivel de API> = 8, puede usar este fragmento:

dialog.setOnShowListener(new OnShowListener() {
    @Override
     public void onShow(DialogInterface dialog) {
         InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
         imm.showSoftInput(textEdit, InputMethodManager.SHOW_IMPLICIT);
    }
});

No he encontrado una solución para niveles de API más bajos ...

Por cierto: este fragmento no siempre funciona en el emulador. No sé por qué.

Gian U.
fuente
2
No estoy tan interesado en esta solución alternativa específica como en por qué no está funcionando en primer lugar. Además, en realidad no quiero que el teclado se muestre con el cuadro de diálogo, quiero que aparezca cuando EditText gane el foco, como el comportamiento de un EditText normal.
Paul
1
Esto funcionó para mí. Solo use AlertDialog dialog = builder.create();antes y dialog.show();después de lo anterior si está usando AlertDialog.Builder
Matt Connolly
1
Este es el único que funcionó para mí. Tampoco creo que sea una solución alternativa, tiene sentido cuando lo lee con la respuesta a continuación citando los documentos de Android sobre por qué no puede solicitar el enfoque hasta que se muestre el cuadro de diálogo.
Mick Byrne
17

Si lee la documentación de AlertDialog, encontrará allí:

La clase AlertDialog se encarga de configurar automáticamente * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM * para usted en función de si alguna de las vistas en el diálogo devuelve verdadero desde View.onCheckIsTextEditor () . Por lo general, desea este conjunto para un cuadro de diálogo sin editores de texto, de modo que se coloque en la parte superior de la interfaz de usuario del método de entrada actual. Puede modificar este comportamiento forzando la bandera a su modo deseado después de llamar a onCreate .

Tuve el problema que mencionaste con EditText en ListView dentro de un diálogo. Lo arreglé sobrescribiendo la clase de vista personalizada (en mi caso ListView) con mi propio FocusableListView, con solo un método sobrescrito:

public class FocusableListView extends ListView {

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

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

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

    @Override
    public boolean onCheckIsTextEditor() {
        // this is where the magic happens
        return true;
    }
}

Entonces lo estoy usando en el archivo de diseño como:

<?xml version="1.0" encoding="UTF-8"?>
<com.myexample.wiget.FocusableListView 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:descendantFocusability="beforeDescendants"
android:layout_height="wrap_content" />

Puede sobrescribir el RelativeLayout en su caso de la misma manera y debería funcionar.

philips77
fuente
funciona perfectamente, pero Android Studio (versión 1.5.1) no
muestra el
9

Esto es lo que funcionó para mí. Cree el AlertDialog.Builder, establezca el título, positiveButton, negativeButton. Después de hacer esto:

    AlertDialog dialog = builder.create();
    dialog.getWindow().clearFlags( WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
    dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
    dialog.show();
    editText.requestFocus();

No necesitas usar builder.show();.

André Luiz Reis
fuente
Gracias André, eres el hombre. Probé tantas soluciones aquí en SO. Este es el único que está trabajando
productioncoder
8

El código anterior es muy útil. Pero debe llamar al método "show" después del método "create" (no sé por qué, pero solo esto funciona en mi diálogo con EditText en ListView). En el método onCreateDialog:

@Override
protected Dialog onCreateDialog(int id) {
  switch (id) {
    case YOUR_DIALOG_ID: {
        //...
        AlertDialog a = new AlertDialog.Builder(this)./*
        ... set the properties here
        */
        .create();
        a.show(); //!!! this is very important to call the "show" method
        a.getWindow().clearFlags(
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
        return a;
    }
  //...
  }
  return null;
}
iLya2IK
fuente
¿Ese código realmente funciona? a se inicializa como un AlertDialog pero el constructor es un constructor. Los constructores tienen un método de creación que devuelve un diálogo, los diálogos tienen un método de mostrar para mostrarlos.
Paul
@Paul Disculpe. El código estaba realmente mal en la parte de la creación de un diálogo por parte de un constructor. Lo corregí.
iLya2IK
7

¡Gracias! Tengo un TextEdit incrustado en la última fila de ListView incrustado en el fragmento de diálogo de alerta. Usé su solución de borrar las banderas como una publicación ejecutable y ahora funciona perfectamente.

    @Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
    builder.setTitle("My Title");
    m_adapter = new MyAdapter(getContext());
    builder.setAdapter(m_adapter, new OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int which) {
            // TODO Auto-generated method stub

        }
    }); 

    final AlertDialog dialog = builder.create();
    final ListView listView = dialog.getListView();
    listView.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {

        }
    });

    listView.post(new Runnable() {

        @Override
        public void run() {
            dialog.getWindow().clearFlags(
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                    WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);              
        }
    });
    return dialog;
}
farid_z
fuente
4

He aquí una forma de hacerlo:

    final Window dialogWindow = dialog.getWindow();
    dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
    dialogWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
desarrollador de Android
fuente
2

Me gustaría agregar algo a la respuesta de Paul y al comentario de Alexander .

Yo mismo tengo un cuadro de diálogo que se creó en el onCreateDialog()método, que (parece) requerir regresar dialog.show();, por lo que no puede agregar los parámetros de diseño al cuadro de diálogo donde se crea el cuadro de diálogo. Para solucionar esto, simplemente mantenga su onCreateDialog()método igual y agregue un onResume()método de la siguiente manera:

@Override
public void onResume() {
    super.onResume();
    Dialog dialog = getDialog();
    dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
    dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
}

Esto debería funcionar, me funciona, afortunadamente. He estado en este caso durante bastante tiempo.

Timmiej93
fuente
0

código completo para mostrar el teclado en el diálogo:

public void onFocusChange(View v, boolean hasFocus) {
    Log.v("onFocusChange", hasFocus + " " + showkeyboard);
    if (hasFocus) {
        if (showkeyboard++ == 0) {
            alertDialog.getWindow().clearFlags(
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
            alertDialog.getWindow().setSoftInputMode(
                    WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        } else {
            showkeyboard = 1;
        }
    }
}
ángeles sonriendo
fuente
1
tratando de explicar tu respuesta. No pongas solo código. Dar una respuesta específica y una explicación sobre el código respectivo ...
Sandip Armal Patil
0
This worked for me ----
editText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
//dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
//dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
//dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
InputMethodManager mgr = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
mgr.showSoftInput(v, InputMethodManager.SHOW_FORCED);
editText.setFocusable(true);
}
});
Manish Sain
fuente
0

simplemente agregue debajo de codeLine:

// para mostrar el teclado automáticamente mientras editText está en dialog dialog.getWindow (). setSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);

Mosayeb Masoumi
fuente