Android: EditText dans Dialog ne tire pas le clavier

J’ai donc ce qui semble être un problème commun, à savoir que le EditText de ma boîte de dialog ne s’affiche pas lorsqu’il est actif. J’ai vu plusieurs solutions, telles que celle-ci , celle-ci et celle-ci (et beaucoup d’autres), mais je n’ai jamais vu d’explication satisfaisante de la raison pour laquelle cela se produit.

Je préférerais de loin que android utilise son propre comportement par défaut pour EditTexts plutôt que de créer le mien, mais il semble que tout le monde (dans ces threads) ait accepté que le comportement par défaut de EditTexts dans Dialogs soit de donner un curseur et aucun clavier. Pourquoi ça serait?

Pour l’enregistrement, aucune de ces solutions ne semble fonctionner pour moi – le plus proche que j’ai pu faire est de forcer un clavier à apparaître sous la boîte de dialog (en utilisant InputMethodManager.toggleSoftKeyboard (*)). Ma configuration particulière est API15, le EditText apparaît dans un pied de page sur un ListView dans un AlertDialog. EditText android: focusable = “true” est défini et onFocusChangeListener reçoit les événements de focus.

Modifier:

Comme demandé, voici l’extrait de code spécifique avec lequel je travaille. Je ne m’embêterai pas avec l’ensemble de la mise en page, mais dans cette application spécifique, EditText apparaît en réponse à une pression sur un bouton de la boîte de dialog (similaire à une vue d’action ). Il est contenu dans un RelativeLayout qui a par défaut la visibilité “disparu”:

     

Le code qui construit ceci définit la visibilité de relativeLayout sur “Visible” (et masque les autres éléments de l’interface utilisateur). Cela devrait être suffisant pour accéder au clavier lorsque EditText se concentre, en fonction de mon expérience avec EditText. Cependant, pour une raison quelconque, ce n’est pas le cas. Je peux définir le suivant surFocusChangeListener:

  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.")); } } }); 

En utilisant cette configuration, lorsque j’entre pour la première fois dans EditText, le onFocusChangedListener se déclenche et génère un journal qui ressemble invariablement à ceci:

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

Le clavier apparaît et disparaît, probablement parce que je le bascule deux fois, mais même lorsque je m’assure qu’il rest en place, il se trouve derrière la fenêtre de dialog (dans une zone grisée) et il n’y a aucun moyen d’y accéder sans fermer la boîte de dialog .

Cela dit, je voudrais souligner que même si je peux être en mesure de faire fonctionner ce travail, je suis principalement intéressé à trouver une raison simple pour laquelle EditText ne se déclenche pas en premier lieu, et pourquoi cela semble être si banal!

OK, donc après avoir beaucoup lu, j’ai compris pourquoi cela pose problème et je n’ai pas besoin de contourner ce problème.

Le problème semble être (du moins dans mon cas), puisque l’endroit où vous entrez du texte est initialement caché (ou nested ou quelque chose), AlertDialog définit automatiquement l’indicateur WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM (ou une combinaison de cela et WindowManager). .LayoutParams.FLAG_NOT_FOCUSABLE) pour que les choses ne déclenchent pas une entrée logicielle.

Le moyen que j’ai trouvé pour résoudre ce problème est d’append la ligne suivante après la création de la boîte de dialog:

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

Une fois cela fait, le EditText agit comme un EditText normal, pas de kludges ou de solutions de contournement nécessaires.

J’ai le même problème dans ma propre application. Si vous développez pour le niveau API> = 8, vous pouvez utiliser cet extrait:

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

Je n’ai pas trouvé de solution pour les niveaux d’API inférieurs …

BTW: Cet extrait ne fonctionne pas toujours sur un émulateur. Je ne sais pas pourquoi.

Si vous lisez la documentation AlertDialog, vous y trouverez:

La classe AlertDialog prend en charge la définition automatique de * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM * selon que des vues de la boîte de dialog renvoient true à View.onCheckIsTextEditor () . En général, vous souhaitez que cet ensemble soit défini pour un dialog sans éditeur de texte, de sorte qu’il soit placé au-dessus de l’interface utilisateur de la méthode de saisie actuelle. Vous pouvez modifier ce comportement en forçant l’indicateur à utiliser le mode souhaité après avoir appelé onCreate .

J’ai eu le problème que vous avez mentionné avec EditText dans ListView dans un dialog. Je l’ai corrigé en écrasant la classe de vue personnalisée (dans mon cas ListView) avec ma propre FocusableListView, avec une seule méthode remplacée:

 public class FocusableListView extends ListView { public FocusableListView(Context context) { super(context); } public FocusableListView(Context context, AtsortingbuteSet attrs) { super(context, attrs); } public FocusableListView(Context context, AtsortingbuteSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean onCheckIsTextEditor() { // this is where the magic happens return true; } } 

Ensuite, je l’utilise dans le fichier de mise en page en tant que:

 < ?xml version="1.0" encoding="UTF-8"?>  

Vous pouvez remplacer le RelativeLayout dans votre cas de la même manière et cela devrait fonctionner.

Le code ci-dessus est très utile. Mais vous devez appeler la méthode “show” après la méthode “create” (je ne sais pas pourquoi, mais seulement cela fonctionne dans mon dialog avec EditText dans ListView). Dans la méthode 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; } 

Je vous remercie! J’ai un TextEdit incorporé dans la dernière ligne de ListView incorporé dans le fragment de dialog d’alerte. J’ai utilisé votre solution pour effacer les drapeaux en tant que post-exécutable et maintenant cela fonctionne parfaitement.

  @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; } 

C’est ce qui a fonctionné pour moi. Créez le AlertDialog.Builder, définissez le titre, positifButton, negativeButton. Après cela:

  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(); 

Vous n’avez pas besoin d’utiliser builder.show(); .

Voici une façon de le faire:

  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); 

J’aimerais append à la réponse de Paul et au commentaire d’Alexander .

J’ai moi-même une boîte de dialog créée dans la méthode onCreateDialog() , qui (semble-t-il) nécessite de renvoyer dialog.show(); , par conséquent, vous ne pouvez pas append les layoutparams à la boîte de dialog dans laquelle la boîte de dialog est créée. Pour contourner ce onCreateDialog() , conservez la même méthode onCreateDialog() et ajoutez une méthode onResume() comme suit:

 @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); } 

Cela devrait faire l’affaire, ça marche pour moi, heureusement. Ont été sur ce cas depuis un certain temps.

code complet pour afficher le clavier dans la boîte de dialog:

 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; } } } 
 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); } });