Fermer / masquer le clavier logiciel Android



Answers

Pour aider à clarifier cette folie, je voudrais commencer par présenter des excuses au nom de tous les utilisateurs d'Android pour le traitement carrément ridicule de Google du clavier logiciel. La raison pour laquelle il y a tant de réponses, chacune différente, pour la même question simple est que cette API, comme beaucoup d'autres sur Android, est horriblement conçue. Je ne peux penser à aucune façon polie de l'énoncer.

Je veux cacher le clavier. Je m'attends à fournir Android avec la déclaration suivante: Keyboard.hide() . La fin. Merci beaucoup. Mais Android a un problème. Vous devez utiliser InputMethodManager pour masquer le clavier. OK, d'accord, c'est l'API d'Android au clavier. MAIS! Vous devez avoir un Context pour avoir accès à l'IMM. Maintenant, nous avons un problème. Je peux vouloir cacher le clavier d'une classe statique ou d'utilité qui n'a aucune utilisation ou nécessité pour n'importe quel Context . ou Et pire encore, l'IMM nécessite que vous spécifiiez quelle View (ou pire, quelle Window ) vous voulez cacher le clavier.

C'est ce qui rend le clavier si difficile. Cher Google: Quand je cherche la recette pour un gâteau, il n'y a pas de RecipeProvider sur Terre qui refuserait de me fournir la recette à moins que je ne réponde d'abord à OMS le gâteau sera mangé par ET où il sera mangé !!

Cette triste histoire se termine par la vilaine vérité: pour cacher le clavier Android, vous devrez fournir 2 formes d'identification: un Context et soit une View ou une Window .

J'ai créé une méthode utilitaire statique qui peut faire le travail très solidement, à condition de l'appeler à partir d'une Activity .

public static void hideKeyboard(Activity activity) {
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    //Find the currently focused view, so we can grab the correct window token from it.
    View view = activity.getCurrentFocus();
    //If no view currently has focus, create a new one, just so we can grab a window token from it
    if (view == null) {
        view = new View(activity);
    }
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

Sachez que cette méthode utilitaire fonctionne UNIQUEMENT lorsqu'elle est appelée depuis une Activity ! La méthode ci-dessus appelle getCurrentFocus de l' Activity cible pour getCurrentFocus le jeton de la fenêtre appropriée.

Mais supposons que vous vouliez cacher le clavier d'un EditText hébergé dans un DialogFragment ? Vous ne pouvez pas utiliser la méthode ci-dessus pour cela:

hideKeyboard(getActivity()); //won't work

Cela ne fonctionnera pas car vous passerez une référence à l' Activity hôte du Fragment , qui n'aura aucun contrôle ciblé pendant que le Fragment est affiché! Hou la la! Donc, pour cacher le clavier des fragments, j'ai recours au niveau inférieur, plus commun et plus laide:

public static void hideKeyboardFrom(Context context, View view) {
    InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

Voici quelques informations supplémentaires glanées à partir de plus de temps perdu à courir après cette solution:

À propos de windowSoftInputMode

Il y a encore un autre point de discorde à connaître. Par défaut, Android attribue automatiquement le focus initial au premier EditText ou au premier contrôle focalisable de votre Activity . Il s'ensuit naturellement que InputMethod (généralement le clavier logiciel) répondra à l'événement focus en s'affichant. L'attribut windowSoftInputMode dans AndroidManifest.xml , lorsqu'il est défini sur stateAlwaysHidden , indique au clavier d'ignorer ce focus initial attribué automatiquement.

<activity
    android:name=".MyActivity"
    android:windowSoftInputMode="stateAlwaysHidden"/>

Presque incroyablement, il semble ne rien faire pour empêcher l'ouverture du clavier lorsque vous touchez le contrôle (sauf si focusable="false" et / ou focusableInTouchMode="false" sont assignés au contrôle). Apparemment, le paramètre windowSoftInputMode s'applique uniquement aux événements de mise au point automatique, et non aux événements déclenchés à partir d'événements tactiles.

Par conséquent, stateAlwaysHidden est TRÈS mal nommé. Il devrait peut-être s'appeler ignoreInitialFocus place.

J'espère que cela t'aides.

MISE À JOUR: plus de façons d'obtenir un jeton de fenêtre

S'il n'y a pas de vue focalisée (par exemple, si vous venez de modifier des fragments), il existe d'autres vues qui fourniront un jeton de fenêtre utile.

Ce sont des alternatives pour le code ci-dessus if (view == null) view = new View(activity); Ceux-ci ne se réfèrent pas explicitement à votre activité.

Dans une classe de fragments:

view = getView().getRootView().getWindowToken();

Étant donné un fragment de fragment tant que paramètre:

view = fragment.getView().getRootView().getWindowToken();

À partir de votre corps de contenu:

view = findViewById(android.R.id.content).getRootView().getWindowToken();

UPDATE 2: Effacer le focus pour éviter d'afficher à nouveau le clavier si vous ouvrez l'application depuis l'arrière-plan

Ajoutez cette ligne à la fin de la méthode:

view.clearFocus();

Question

J'ai un EditText et un Button dans ma disposition.

Après avoir écrit dans le champ d'édition et cliqué sur le Button , je veux cacher le clavier virtuel. Je suppose que c'est un simple code, mais où puis-je trouver un exemple?




Simple and Easy to use method, just call hideKeyboardFrom(YourActivity.this); to hide keyboard

/**
 * This method is used to hide keyboard
 * @param activity
 */
public static void hideKeyboardFrom(Activity activity) {
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}



La réponse courte

Dans votre écouteur OnClick appelez l' onEditorAction du EditText avec IME_ACTION_DONE

button.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        someEditText.onEditorAction(EditorInfo.IME_ACTION_DONE)
    }
});

Le drill-down

Je pense que cette méthode est meilleure, plus simple et plus alignée avec le modèle de conception d'Android. Dans l'exemple simple ci-dessus (et généralement dans la plupart des cas courants), vous aurez un EditText qui a / avait focus et c'est généralement lui qui EditText le clavier (il est définitivement capable de l'invoquer dans beaucoup de scénarios communs). De la même manière, il devrait être celui qui libère le clavier, ce qui peut généralement être fait par un ImeAction . Il suffit de voir comment un EditText avec android:imeOptions="actionDone" se comporte, vous voulez atteindre le même comportement par les mêmes moyens.

Cochez cette réponse




protected void hideSoftKeyboard(EditText input) {
    input.setInputType(0);
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(input.getWindowToken(), 0);    
}



S'il vous plaît essayez ce code ci-dessous dans oncreate ()

EditText edtView = (EditText) findViewById (R.id.editTextConvertValue); edtView.setInputType (0);




J'ai une autre solution pour cacher le clavier:

InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);

Ici passez HIDE_IMPLICIT_ONLY à la position de showFlag et 0 à la position de hiddenFlag . Il fermera avec force le clavier souple.




Just use this optimized code in your activity:

if (this.getCurrentFocus() != null) {
    InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
    inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}



Thanks to this SO answer , I derived the following which, in my case, works nicely when scrolling through the the fragments of a ViewPager...

private void hideKeyboard() {   
    // Check if no view has focus:
    View view = this.getCurrentFocus();
    if (view != null) {
        InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
        inputManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

private void showKeyboard() {   
    // Check if no view has focus:
    View view = this.getCurrentFocus();
    if (view != null) {
        InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
        inputManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
    }
}



Alternativement à cette solution globale, si vous vouliez fermer le clavier logiciel de n'importe où sans avoir de référence au champ (EditText) qui était utilisé pour ouvrir le clavier, mais que vous vouliez le faire si le champ était focalisé, vous pouviez utiliser ceci (d'une activité):

if (getCurrentFocus() != null) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}



Saurabh Pareek a la meilleure réponse jusqu'à présent.

Pourrait aussi bien utiliser les bons drapeaux, cependant.

/* hide keyboard */
((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
    .toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

/* show keyboard */
((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
    .toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);

Exemple d'utilisation réelle

/* click button */
public void onClick(View view) {      
  /* hide keyboard */
  ((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
      .toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

  /* start loader to check parameters ... */
}

/* loader finished */
public void onLoadFinished(Loader<Object> loader, Object data) {
    /* parameters not valid ... */

    /* show keyboard */
    ((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
        .toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);

    /* parameters valid ... */
}



J'ai l'affaire, où mon EditTextpeut être situé également dans un AlertDialog, de sorte que le clavier doit être fermé sur le rejet. Le code suivant semble fonctionner n'importe où:

public static void hideKeyboard( Activity activity ) {
    InputMethodManager imm = (InputMethodManager)activity.getSystemService( Context.INPUT_METHOD_SERVICE );
    View f = activity.getCurrentFocus();
    if( null != f && null != f.getWindowToken() && EditText.class.isAssignableFrom( f.getClass() ) )
        imm.hideSoftInputFromWindow( f.getWindowToken(), 0 );
    else 
        activity.getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN );
}



If you want to close the soft keyboard during a unit or functional test, you can do so by clicking the "back button" from your test:

// Close the soft keyboard from a Test
getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);

I put "back button" in quotes, since the above doesn't trigger the onBackPressed() for the Activity in question. It just closes the keyboard.

Make sure to pause for a little while before moving on, since it takes a little while to close the back button, so subsequent clicks to Views, etc., won't be registered until after a short pause (1 second is long enough ime).




This worked for me for all the bizarre keyboard behavior

private boolean isKeyboardVisible() {
    Rect r = new Rect();
    //r will be populated with the coordinates of your view that area still visible.
    mRootView.getWindowVisibleDisplayFrame(r);

    int heightDiff = mRootView.getRootView().getHeight() - (r.bottom - r.top);
    return heightDiff > 100; // if more than 100 pixels, its probably a keyboard...
}

protected void showKeyboard() {
    if (isKeyboardVisible())
        return;
    InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    if (getCurrentFocus() == null) {
        inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
    } else {
        View view = getCurrentFocus();
        inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_FORCED);
    }
}

protected void hideKeyboard() {
    if (!isKeyboardVisible())
        return;
    InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    View view = getCurrentFocus();
    if (view == null) {
        if (inputMethodManager.isAcceptingText())
            inputMethodManager.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);
    } else {
        if (view instanceof EditText)
            ((EditText) view).setText(((EditText) view).getText().toString()); // reset edit text bug on some keyboards bug
        inputMethodManager.hideSoftInputFromInputMethod(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}



For my case, I was using the a SearchView in the actionbar. After a user performs a search, the keyboard would pop open again.

Using the InputMethodManager did not close the keyboard. I had to clearFocus and set the focusable of the search view to false:

mSearchView.clearFocus();
mSearchView.setFocusable(false);



J'utilise un clavier personnalisé pour entrer un numéro Hex afin que je ne puisse pas afficher le clavier IMM ...

Dans v3.2.4_r1 setSoftInputShownOnFocus(boolean show) été ajouté pour contrôler la météo ou ne pas afficher le clavier quand un TextView obtient le focus, mais il est toujours caché donc la réflexion doit être utilisée:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
    try {
        Method method = TextView.class.getMethod("setSoftInputShownOnFocus", boolean.class);
        method.invoke(mEditText, false);
    } catch (Exception e) {
        // Fallback to the second method
    }
}

Pour les versions plus anciennes, j'ai obtenu de très bons résultats (mais loin d'être parfaits) avec un OnGlobalLayoutListener , ajouté à l'aide d'un ViewTreeObserver depuis ma vue racine puis en vérifiant si le clavier est affiché comme ceci:

@Override
public void onGlobalLayout() {
    Configuration config = getResources().getConfiguration();

    // Dont allow the default keyboard to show up
    if (config.keyboardHidden != Configuration.KEYBOARDHIDDEN_YES) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(mRootView.getWindowToken(), 0);
    }
}

Cette dernière solution peut afficher le clavier pendant une fraction de seconde et jouer avec les poignées de sélection.

Lorsque le clavier passe en plein écran, onGlobalLayout n'est pas appelé. Pour éviter cela, utilisez TextView#setImeOptions(int) ou dans la déclaration XML TextView:

android:imeOptions="actionNone|actionUnspecified|flagNoFullscreen|flagNoExtractUi"

Mise à jour: Juste trouvé ce que les boîtes de dialogue utilisent pour ne jamais montrer le clavier et fonctionne dans toutes les versions:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
        WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);



Links