Fermer / masquer le clavier logiciel Android

3822

J'ai un EditTextet un Buttondans ma mise en page.

Après avoir écrit dans le champ d'édition et cliqué sur Button, je souhaite masquer le clavier virtuel. Je suppose qu'il s'agit d'un simple morceau de code, mais où puis-je en trouver un exemple?

Lorsque vous touchez à l'extérieur du clavier.

Ak23
la source
13
Et si vous n'avez qu'un seul EditText et plusieurs boutons, comme des cases à cocher et des radios? Le seul endroit où vous avez besoin du clavier est dans le seul EditText. Comment vous enregistrez-vous pour savoir que quelque chose d'autre a été choisi / cliqué afin de cacher le clavier?
AlikElzin-kilaka
14
je me sens stupide. Je ne parviens pas à masquer le clavier sur ICS. J'ai essayé toutes les méthodes ici et leurs combinaisons. En aucune façon. La méthode pour le montrer fonctionne, mais je ne peux pas le cacher, quel que soit le jeton de vent, cacher les drapeaux, les paramètres manifestes ou les bougies à tous les saints. Sur le clavier, je vois toujours ceci: I / LatinIME (396): InputType.TYPE_NULL est spécifié W / LatinIME (396): Classe d'entrée inattendue: inputType = 0x00000000 imeOptions = 0x00000000
rupps
4
/ ** * Cette méthode est utilisée pour masquer le clavier logiciel. * activité @param * / public void hideSoftKeyboard (activité Activity) {InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService (Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow (activity.getCurrentFocus (). getWindowToken (), 0); }
Harshal Benake
cela a fonctionné pour moi
nmxprime
Les appareils augmentant la taille et la résolution de l'écran, le masquage du clavier virtuel devient moins important.
Al-Kathiri Khalid,

Réponses:

2038

Pour aider à clarifier cette folie, je voudrais commencer par m'excuser au nom de tous les utilisateurs d'Android du traitement carrément ridicule de Google pour le 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 dans Android, est horriblement conçue. Je ne peux penser à aucune manière polie de le dire.

Je veux cacher le clavier. Je pense à fournir Android avec l'énoncé suivant: Keyboard.hide(). La fin. Merci beaucoup. Mais Android a un problème. Vous devez utiliser le InputMethodManagerpour masquer le clavier. D'accord, c'est l'API d'Android pour le clavier. MAIS! Vous devez en avoir un Contextpour avoir accès à l'IMM. Maintenant, nous avons un problème. Je peux vouloir cacher le clavier d'une classe statique ou utilitaire qui n'a aucune utilité ou besoin d'aucune Context. ou bien pire, IMM demande que vous spécifiiez de quoi View(ou pire encore, de quoi Window) vous voulez cacher le clavier.

C'est ce qui rend le masquage du clavier si difficile. Cher Google: Quand je recherche la recette d'un gâteau, il n'y a personne RecipeProvidersur Terre qui refuserait de me fournir la recette à moins que je ne réponde d'abord QUI 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: a Contextet soit a Viewsoit a Window.

J'ai créé une méthode utilitaire statique qui peut faire le travail TRÈS solidement, à condition de l'appeler à partir d'un 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 à partir d'un Activity! La méthode ci-dessus appelle getCurrentFocusla cible Activitypour récupérer le jeton de fenêtre approprié.

Mais supposons que vous vouliez cacher le clavier d'un EditTexthé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' Fragmenthôte de Activity, qui n'aura aucun contrôle concentré pendant que le Fragmentest affiché! Hou la la! Donc, pour cacher le clavier des fragments, je recourt au niveau inférieur, plus courant et plus laid:

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

Vous trouverez ci-dessous quelques informations supplémentaires tirées du temps perdu à courir après cette solution:

À propos de windowSoftInputMode

Il y a encore un autre point de discorde à prendre en compte. Par défaut, Android attribuera automatiquement la mise au point initiale au premier EditTextou au contrôle pouvant être mis au point dans votre Activity. Il s'ensuit naturellement que InputMethod (généralement le clavier virtuel) répondra à l'événement de focus en se montrant. L' windowSoftInputModeattribut dans AndroidManifest.xml, lorsqu'il est défini sur stateAlwaysHidden, demande au clavier d'ignorer ce focus initial attribué automatiquement.

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

Presque incroyablement, il ne semble rien faire pour empêcher le clavier de s'ouvrir 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 focus automatique, pas aux événements de focus déclenchés par des événements tactiles.

Par conséquent, stateAlwaysHiddenest TRÈS mal nommé en effet. Il faudrait peut-être l'appeler à la ignoreInitialFocusplace.

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 ciblée (par exemple, si vous venez de changer des fragments), il existe d'autres vues qui fourniront un jeton de fenêtre utile.

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

Dans une classe de fragments:

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

Étant donné un fragment fragmentcomme paramètre:

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

À partir de votre corps de contenu:

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

MISE À JOUR 2: Effacer la mise au point pour éviter d'afficher à nouveau le clavier si vous ouvrez l'application en arrière-plan

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

view.clearFocus();

rmirabelle
la source
2
Très beau résumé. Une chose cependant, si vous lancez une autre activité par dessus, qui déclenche le clavier, le clavier sera toujours présent à votre retour. Correction de cela en supprimant le clavier en utilisant votre méthode lorsque vous quittez l'activité supérieure.
Oyvind
3
@rmirabelle Dans un Fragmentil semble que vous pouvez utilisergetActivity().getWindow().getDecorView()
McX
1
Ce post est génial mais il vous manque deux parties très importantes. Les changements subtils effectués par version et par fabrication. Par exemple, sur un Samsung galaxy s6, nous devons utiliser .clearFocus () avant de masquer le clavier ... sinon le clavier apparaîtra toujours au deuxième clic d'edittext: S
Warpzit
17
google devrait vraiment fournir cet Keyboard.hide();utilitaire
HendraWD
1
[someView] .getContext () << Peut être le cas pour l'activité. C'est toujours le même objet. (Sauf services internes ...)
Oliver Dixon
4419

Vous pouvez forcer Android à masquer le clavier virtuel en utilisant InputMethodManager , en appelant hideSoftInputFromWindow, en passant le jeton de la fenêtre contenant votre vue focalisée.

// Check if no view has focus:
View view = this.getCurrentFocus();
if (view != null) {  
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

Cela forcera le clavier à être caché dans toutes les situations. Dans certains cas, vous voudrez passer en InputMethodManager.HIDE_IMPLICIT_ONLYtant que second paramètre pour vous assurer de ne masquer le clavier que lorsque l'utilisateur ne l'a pas forcé à apparaître (en maintenant le menu enfoncé).

Remarque: Si vous souhaitez le faire dans Kotlin, utilisez: context?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager

Syntaxe de Kotlin

// Check if no view has focus:
 val view = this.currentFocus
 view?.let { v ->
  val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager 
  imm?.hideSoftInputFromWindow(v.windowToken, 0)
 }
Reto Meier
la source
14
Merci, cela semble très bien fonctionner si vous utilisez 0 comme deuxième paramètre. Mais si j'utilise InputMethodManager.HIDE_IMPLICIT_ONLY, le clavier n'est jamais caché (bien que je ne maintienne pas le menu enfoncé). Des indices?
RoflcoptrException
27
Cool. Juste pour clarifier, cela ne le rejette que s'il est présent, mais ne l' empêchera pas d'apparaître, non?
Cheezmeister
15
Il peut être utile d'appeler editText.clearFocus () avant de masquer le softInput
user2224350
111
L'appel fonctionne editText.clearFocus()alors InputMethodManager.HIDE_IMPLICIT_ONLYmême4.1
sprocket12
11
Ce qui a fonctionné pour moi sur 4.4 / htc était l'exécution View focused = getCurrentFocus()pour obtenir ce qui est définitivement la vue actuellement focalisée, l'appel focused.clearFocus(), puis inputMethodManager.hideSoftInputFromWindow(focused.getWindowToken(), 0)(avec des indicateurs clairs).
Ionoclast Brigham
806

Également utile pour masquer le clavier virtuel:

getWindow().setSoftInputMode(
    WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
);

Cela peut être utilisé pour supprimer le clavier logiciel jusqu'à ce que l'utilisateur touche réellement la vue editText.

grenat Ulrich
la source
116
Vous pouvez également obtenir le même effet en ajoutant android: windowSoftInputMode = "stateHidden" sur votre activité dans le manifeste.
BoD
7
J'ai essayé cela dans un fragment (faisant référence à l'activité propriétaire) sur l'API niveau 9 et cela n'a malheureusement pas fonctionné. J'ai essayé de l'appeler dans onResume et onActivityCreated - aucun effet.
AgentKnopf
2
Je travaille dans un dialogue et cela a fonctionné. J'utilise Android 3.2. Je l'ai mis dans la méthode onCreateDialog (Bundle). Cela ne fonctionnait pas dans la méthode onCreate. Dialogue dialog = super.onCreateDialog (savedInstanceState); dialog.getWindow (). setSoftInputMode (WindowManager.LayoutParams. SOFT_INPUT_STATE_ALWAYS_HIDDEN); Le résultat est que ma vue avec EditTexts apparaît sans le clavier. Lorsque l'utilisateur touche un texte d'édition, le clavier s'affiche.
flobacca
4
Cela ne fonctionne pas lorsque le focus est toujours dans un EditText (comme après avoir appuyé sur un bouton). Utilisez la solution de Reto pour cela.
Noumenon
4
Pourquoi remplacer les paramètres du manifeste est-il une mauvaise idée? J'appelle cela à partir d'un fragment. Il n'y a pas de paramètre manifeste qui s'applique à un fragment ...
Greg Ennis
349

J'ai une autre solution pour masquer le clavier:

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

Ici, passez HIDE_IMPLICIT_ONLYà la position showFlaget 0à la position de hiddenFlag. Il fermera de force le clavier logiciel.

Saurabh Pareek
la source
4
Vous utilisez un indicateur de masquage dans le paramètre showflags. Cela ne fonctionne que parce que les constantes utilisent les mêmes entiers. Exemple utilisant les bons drapeaux
Alex
testée sur Android 4.0, j'aime cette solution, car j'ai plusieurs textes d'édition, des boutons sur cette activité, qui peuvent avoir le focus
32
@Mark: Parce que la méthode s'appelle "toggleSoftInput", pas "hideSoftInput" :)
Sver
19
Cette solution affiche le clavier s'il est masqué. Ce n'est pas correct
Michael Katkov
1
@AkashAggarwal - Cela "fonctionne" si vous ignorez le fait que cela ne fonctionnait que pour vous parce que le clavier était visible. (Il bascule la visibilité du clavier: il se cache quand il est affiché, MAIS il le montre quand il est caché !!) Pouvez-vous GARANTIR qu'en toutes circonstances, sur tous les appareils, pour toutes les futures versions d'Android, que le clavier ne sera PAS montrant au moment où vous appelez cela? Si oui, alors allez-y et utilisez-le!
ToolmakerSteve
149

La solution de Meier fonctionne aussi pour moi. Dans mon cas, le niveau supérieur de mon application est un tabHost et je veux masquer le mot-clé lorsque je change d'onglet - j'obtiens le jeton de fenêtre de la vue tabHost.

tabHost.setOnTabChangedListener(new OnTabChangeListener() {
    public void onTabChanged(String tabId) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(tabHost.getApplicationWindowToken(), 0);
    }
}
mckoss
la source
J'ai également réussi à utiliser SearchView. Voir ci-dessous pour ma réponse. Merci mckoss!
Azurespot
139

Veuillez essayer ce code ci-dessous dans onCreate()

EditText edtView=(EditText)findViewById(R.id.editTextConvertValue);
edtView.setInputType(0);
Jeyavel
la source
2
Cette méthode fonctionne comme un moyen de contourner le bogue «impossible de masquer le clavier virtuel » dans 2.0 et 2.1, comme décrit dans code.google.com/p/android/issues/detail?id=7115 ... la méthode hideSoftInputFromWindow ci-dessus n'a pas fonctionné lorsque je l'ai essayé, mais editView.setInputType (0) l'a fait.
Spike Williams
18
C'est légitime par Javadoc (pas un hack) bien que je réécrive la méthode commeeditView.setInputType(InputType.TYPE_NULL);
Bostone
3
cela fonctionne, cependant, il cache l'androïde: indice. j'utilise Android 1.5
Tirtha
c'est idéal lorsque vous devez fermer le clavier à partir d'une boîte de dialogue, n'avez pas besoin d'obtenir une instance ou quoi que ce soit et pouvez l'attribuer à tous les textes d'édition lorsque l'utilisateur appuie sur un bouton qui ferme la boîte de dialogue
I'm_With_Stupid
Cela fonctionne, mais il cache également le curseur. J'ai besoin du curseur, mais pas de clavier système.
Stefan Brendle
129

Mise à jour: je ne sais plus pourquoi cette solution ne fonctionne plus (je viens de tester sur Android 23). Veuillez utiliser à la place la solution de Saurabh Pareek . C'est ici:

InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
//Hide:
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
//Show
imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

Ancienne réponse:

//Show soft-keyboard:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
//hide keyboard :
 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Nguyen Minh Binh
la source
8
Où dois-je placer ce code? J'ai essayé de coller getWindow (). SetSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); dans onCreate () mais le clavier n'est jamais caché
user2236096
ne fonctionne pas, testé dans radioGroup.setOnCheckedChangeListener, API 23
Christian Schäfer
Si vous regardez de plus près, InputMethodManager.HIDE_IMPLICIT_ONLY et InputMethodManager.SHOW_IMPLICIT ont la même valeur, qui est "1", il n'y a donc pas de différence entre ces appels. => ne fonctionne pas
Palejandro
si vous appelez imm.toggleSoftInput (InputMethodManager.HIDE_IMPLICIT_ONLY, 0); alors le clavier apparaîtra à l'écran :) La meilleure implémentation est: github.com/ravindu1024/android-keyboardlistener Honte sur le SDK Android
Duna
I don't know why this solution is not work any more- parce que c'est Android , tout va pouvoir changer, peut-être en partie de mauvais design ... On écrit négligemment, puis on raye tout et on réécrit tout.
King King
89
protected void hideSoftKeyboard(EditText input) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(input.getWindowToken(), 0);    
}
Sreedev R
la source
5
Cela a fonctionné pour moi! Mais pourquoi avez-vous mis input.setInputType (0) ? Je ne pouvais pas interagir avec EditTextView lorsque j'avais cette ligne de code (cela a fonctionné lorsque je l'ai supprimée).
ymerdrengene
Probablement input.getContext().getSystemService(Context.INPUT_METHOD_SERVICE).
CoolMind
J'ai supprimé input.setInputType(0);ce code. Il a changé un comportement de clavier et inputTypepour le EditText.
CoolMind
74

Si toutes les autres réponses ici ne fonctionnent pas pour vous comme vous le souhaitez, il existe un autre moyen de contrôler manuellement le clavier.

Créez une fonction qui gérera certaines des EditTextpropriétés de:

public void setEditTextFocus(boolean isFocused) {
    searchEditText.setCursorVisible(isFocused);
    searchEditText.setFocusable(isFocused);
    searchEditText.setFocusableInTouchMode(isFocused);

    if (isFocused) {
        searchEditText.requestFocus();
    }
}

Ensuite, assurez-vous que l'onFocus du EditTextvous ouvrez / fermez le clavier:

searchEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (v == searchEditText) {
            if (hasFocus) {
                // Open keyboard
                ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(searchEditText, InputMethodManager.SHOW_FORCED);
            } else {
                // Close keyboard
                ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(searchEditText.getWindowToken(), 0);
            }
        }
    }
});

Maintenant, chaque fois que vous souhaitez ouvrir le clavier manuellement, appelez:

setEditTextFocus(true);

Et pour clôturer l'appel:

setEditTextFocus(false);
Rotemmiz
la source
+1 - Si vous souhaitez démarrer une activité avec un clavier fermé, utilisez cette solution et ajoutez un onclicklistener qui définit setEditTextFocus (true). Fonctionne comme le charme!
schlingel
J'ai obtenu «Impossible de résoudre le contexte du symbole», sur la 7e et la 10e ligne du deuxième bloc de code.
gimmegimme
Utilisez getContext () à la place
Rotemmiz
61

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

Pourrait aussi bien utiliser les bons drapeaux.

/* 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 ... */
}
Alex
la source
1
C'est le plus efficace pour la dernière version. Il faudra toujours le modifier pour les anciennes versions. Surtout avant la v3.
Alex
2
@Mazen: usefragment.getActivity().getSystemService();
Johan S
C'est la réponse la plus complète, couvrant à la fois l'affichage et la dissimulation.
André Staltz
4
Non. Sur mon Samsung Tab, Android 5.0, le code dit "masquer le clavier" ci-dessus fera basculer le clavier logiciel - s'il est déjà masqué, il le montrera. Il y a une raison pour laquelle cette fonction a TOGGLE dans le nom.
ToolmakerSteve
57

de tant de recherche, ici j'ai trouvé une réponse qui fonctionne pour moi

// Show soft-keyboard:
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

// Hide soft-keyboard:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
shontauro
la source
Le seul qui a fonctionné pour moi pour un Motorola avec Android 5.1
GMX
55

La réponse courte

Dans votre OnClickauditeur, appelez le onEditorActiondes EditTextavecIME_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 EditTextqui a / avait le focus et c'est aussi généralement celui qui invoque le clavier en premier lieu (il est certainement capable de l'invoquer dans de nombreux scénarios courants). De la même manière, ce devrait être celui qui relâche le clavier, ce qui peut généralement être fait par un ImeAction. Il suffit de voir comment se comporte un EditTextavec android:imeOptions="actionDone", vous voulez obtenir le même comportement par les mêmes moyens.


Vérifiez cette réponse connexe

Alex.F
la source
Telle est la réponse. Seule méthode qui fonctionne en version croisée. Je suis revenu à cette question pour poster cette réponse car je ne pensais pas que quelqu'un d'autre le savait
Noah Passalacqua
Ce devrait être la bonne réponse. Au lieu de tromper Android pour cacher le clavier alors qu'il devrait vraiment être là, nous lui disons que l'utilisateur a terminé, ce qui déclenche à son tour la même ImeAction [nom stupide, je l'admets] comme si l'utilisateur avait cliqué sur "TERMINÉ" sur le clavier . De cette façon, cela ne fait aucune différence si l'utilisateur confirme la saisie sur le clavier ou appuie sur le bouton UI.
Oliver Hausler
46

Cela devrait fonctionner:

public class KeyBoard {

    public static void show(Activity activity){
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY); // show
    }

    public static void hide(Activity activity){
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); // hide
    }

    public static void toggle(Activity activity){
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
        if (imm.isActive()){
            hide(activity); 
        } else {
            show(activity); 
        }
    }
}

KeyBoard.toggle(activity);
slinden77
la source
Fonctionné en partie, même si le clavier était masqué "isActive ()" renvoie false!
jusqu'au
Bien sûr que c'est le cas, c'est censé le faire. Ou peut-être que je ne te comprends pas. Quoi qu'il en soit, vous pouvez compléter la classe avec hide()et les show()méthodes pour avoir plus de contrôle sur le moment où elle doit s'afficher et quand elle ne le doit pas. Fonctionne pour moi, je l'ai fait aussi :) Je vais éditer l'exemple
slinden77
@YoushaAleayoub oui, ce sera le cas. KeyBoard.toggle(fragment.getActivity())
slinden77
@ slinden77, lol, je parle de votre réponse ... pas celle que vous avez commentée. Donc, cette réponse ne fonctionnera toujours pas.
Yousha Aleayoub
@YoushaAleayoub uhm oui ça va. La question d'origine ne mentionne pas de fragments, c'est vous qui avez mentionné des fragments. Ma réponse est donc parfaitement valable. Pour l'utiliser avec des fragments, appelez la méthode différemment de a Fragment, comme un commenté. Apprenez à utiliser les méthodes, puis revenez. Vous confondez les gens avec vos réponses stupides
slinden77
43

J'utilise un clavier personnalisé pour saisir un numéro Hex donc je ne peux pas faire apparaître le clavier IMM ...

Dans la v3.2.4_r1 a setSoftInputShownOnFocus(boolean show)été ajouté pour contrôler la météo ou pour ne pas afficher le clavier lorsqu'un TextView obtient le focus, mais son 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 à ViewTreeObserverpartir de 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 perturbe les poignées de sélection.

Lorsque le clavier entre 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: vient de trouver ce que les boîtes de dialogue utilisent pour ne jamais afficher le clavier et fonctionne dans toutes les versions:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
        WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
sergio91pt
la source
Je vous remercie. Les deux drapeaux FLAG_ALT_FOCUSABLE_IM et FLAG_ALT_FOCUSABLE_IM sont en fait la seule chose qui a aidé dans mon cas. Je ne voulais pas qu'un clavier soit affiché dans mon activité - pas même lorsque l'utilisateur a cliqué sur un edittext. (J'ai fait mon propre "clavier").
Daniel Novak
Solution intéressante, cependant, si votre activité avant n'est pas en plein écran, le clavier est visible derrière. L'aide au déplacement du curseur du clavier est également toujours visible. Et ce n'est pas skinnable.
halxinate
Je suis d'accord. De toutes les manières possibles, seule la méthode getWindow (). SetFlags () fonctionne, au moins sur le stock Android 5.1. Notez que setSoftInputShownOnFocus () est désormais setShowSoftInputOnFocus () et n'est plus masqué mais ne fonctionne pas, du moins pas lorsque l'utilisateur touche le champ.
olefevre
Votre «mise à jour» était la seule solution de travail pour moi. Je cherche une solution au moins deux heures :)
Stefan Brendle
33
public void setKeyboardVisibility(boolean show) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    if(show){
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
    }else{
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),0);
    }
}
shobhan
la source
30

J'ai passé plus de deux jours à travailler sur toutes les solutions publiées dans le fil et je les ai trouvées manquantes d'une manière ou d'une autre. Mon exigence exacte est d'avoir un bouton qui, avec une fiabilité à 100%, affichera ou masquera le clavier à l'écran. Lorsque le clavier est dans son état masqué, il ne doit pas réapparaître, quels que soient les champs de saisie sur lesquels l'utilisateur clique. Lorsqu'il est dans son état visible, le clavier ne doit pas disparaître, quels que soient les boutons sur lesquels l'utilisateur clique. Cela doit fonctionner sur Android 2.2+ jusqu'aux derniers appareils.

Vous pouvez voir une implémentation fonctionnelle de cela dans mon application RPN propre .

Après avoir testé de nombreuses réponses suggérées sur un certain nombre de téléphones différents (y compris les appareils Froyo et Gingerbread), il est devenu évident que les applications Android peuvent de manière fiable:

  1. Masquez temporairement le clavier. Il réapparaîtra lorsqu'un utilisateur concentre un nouveau champ de texte.
  2. Montrez le clavier lorsqu'une activité démarre et définissez un indicateur sur l'activité indiquant qu'ils doivent toujours être visibles. Ce drapeau ne peut être défini que lorsqu'une activité est en cours d'initialisation.
  3. Marquez une activité pour ne jamais montrer ou autoriser l'utilisation du clavier. Ce drapeau ne peut être défini que lorsqu'une activité est en cours d'initialisation.

Pour moi, masquer temporairement le clavier ne suffit pas. Sur certains appareils, il réapparaîtra dès qu'un nouveau champ de texte sera mis au point. Comme mon application utilise plusieurs champs de texte sur une seule page, la mise au point d'un nouveau champ de texte fera réapparaître le clavier masqué.

Malheureusement, les éléments 2 et 3 de la liste ne fonctionnent que lorsque la fiabilité d'une activité est démarrée. Une fois que l'activité est devenue visible, vous ne pouvez plus masquer ou afficher le clavier de façon permanente. L'astuce consiste à redémarrer réellement votre activité lorsque l'utilisateur appuie sur le bouton à bascule du clavier. Dans mon application, lorsque l'utilisateur appuie sur le bouton à bascule du clavier, le code suivant s'exécute:

private void toggleKeyboard(){

    if(keypadPager.getVisibility() == View.VISIBLE){
        Intent i = new Intent(this, MainActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        Bundle state = new Bundle();
        onSaveInstanceState(state);
        state.putBoolean(SHOW_KEYBOARD, true);
        i.putExtras(state);

        startActivity(i);
    }
    else{
        Intent i = new Intent(this, MainActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        Bundle state = new Bundle();
        onSaveInstanceState(state);
        state.putBoolean(SHOW_KEYBOARD, false);
        i.putExtras(state);

        startActivity(i);
    }
}

Cela provoque l'enregistrement de l'activité en cours dans un ensemble, puis l'activité démarre, en passant par un booléen qui indique si le clavier doit être affiché ou masqué.

Dans la méthode onCreate, le code suivant est exécuté:

if(bundle.getBoolean(SHOW_KEYBOARD)){
    ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(newEquationText,0);
    getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}
else{
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
            WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
}

Si le clavier virtuel doit être affiché, alors InputMethodManager est invité à afficher le clavier et la fenêtre est invitée à rendre l'entrée logicielle toujours visible. Si le clavier virtuel doit être masqué, le WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM est défini.

Cette approche fonctionne de manière fiable sur tous les appareils sur lesquels j'ai testé - depuis un téléphone HTC de 4 ans exécutant Android 2.2 jusqu'à un Nexus 7 exécutant 4.2.2. Le seul inconvénient de cette approche est que vous devez être prudent avec la manipulation du bouton de retour. Comme mon application n'a essentiellement qu'un seul écran (c'est une calculatrice), je peux remplacer onBackPressed () et revenir à l'écran d'accueil des appareils.

Luke Sleeman
la source
1
solution de contournement élaborée, mais je pense que c'est tout simplement trop, pour recréer des milliers d'objets juste pour cacher le clavier. Je ne sais pas qui a conçu IMM pour Android, mais ça sent comme un Windows APi. À mon avis, un bon IME devrait avoir deux méthodes: cacher et montrer :-)
rupps
C'est tout à fait vrai, mais ma solution de contournement a un avantage - cela fonctionne toujours! Il n'y a pas d'autre solution que je pourrais trouver qui permuterait toujours le clavier, quels que soient les champs de l'interface utilisateur qui ont le focus, ce que l'utilisateur a fait pour basculer et le clavier et quelle version d'Android ils exécutent: - \
Luke Sleeman
Mec, je suis totalement désespéré de cacher le clavier. J'ai essayé des milliers de choses et personne ne fonctionne. Mais votre solution de contournement est trop pour moi, je devrais recréer comme 10 fragments, initialiser des services, supprimer beaucoup de références faibles ... vous savez? le GC jetterait juste comme 25mb: S ... Toujours à la recherche d'un moyen fiable de le faire :(
rupps
@Dmitry et bien ce n'est pas un monde bonjour ... c'est une application complexe pour les tablettes. Je refuse de le décharger totalement de la mémoire juste pour cacher un clavier idiot ... Quoi qu'il en soit, j'ai trouvé quelque chose qui fonctionne en combinant les mille solutions proposées ici :)
rupps
27

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

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

Grâce à cette réponse SO , j'ai dérivé les éléments suivants qui, dans mon cas, fonctionnent bien lors du défilement des fragments d'un 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);
    }
}
interdiction de géo-ingénierie
la source
21

Les réponses ci-dessus fonctionnent pour différents scénarios, mais si vous souhaitez masquer le clavier dans une vue et que vous avez du mal à obtenir le bon contexte, essayez ceci:

setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        hideSoftKeyBoardOnTabClicked(v);
    }
}

private void hideSoftKeyBoardOnTabClicked(View v) {
    if (v != null && context != null) {
        InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

et pour que le contexte le récupère du constructeur :)

public View/RelativeLayout/so and so (Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    this.context = context;
    init();
}
Ash
la source
18

Si vous souhaitez fermer le clavier virtuel lors d'un test unitaire ou fonctionnel, vous pouvez le faire en cliquant sur le "bouton retour" de votre test:

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

Je mets "bouton retour" entre guillemets, car ce qui précède ne déclenche pas le onBackPressed()pour l'activité en question. Il ferme simplement le clavier.

Assurez-vous de faire une pause un peu avant de continuer, car il faut un peu de temps pour fermer le bouton de retour, de sorte que les clics ultérieurs vers Vues, ​​etc., ne seront enregistrés qu'après une courte pause (1 seconde est assez longue ime ).

Peter Ajtai
la source
16

Voici comment vous le faites dans Mono pour Android (AKA MonoDroid)

InputMethodManager imm = GetSystemService (Context.InputMethodService) as InputMethodManager;
if (imm != null)
    imm.HideSoftInputFromWindow (searchbox.WindowToken , 0);
Ian Vink
la source
1
Qu'y a-t-il searchboxdans l'extrait?
PCoder
16

Cela a fonctionné pour moi pour tout le comportement bizarre du clavier

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);
    }
}
Pinhassi
la source
1
Je pense que j'ai essayé 10 réponses avant celle-ci. Avait perdu tout espoir. Merci mec.
Bolling
Qu'est-ce que mRootView?
justdan0227
14

Ajoutez à votre activité android:windowSoftInputMode="stateHidden"dans le fichier manifeste. Exemple:

<activity
            android:name=".ui.activity.MainActivity"
            android:label="@string/mainactivity"
            android:windowSoftInputMode="stateHidden"/>
NickUnuchek
la source
14

Méthode simple et facile à utiliser, appelez simplement hideKeyboardFrom (YourActivity.this); masquer le clavier

/**
 * 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);
}
Naveed Ahmad
la source
13

Utilisez simplement ce code optimisé dans votre activité:

if (this.getCurrentFocus() != null) {
    InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
    inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
Hamid FzM
la source
Fonctionne bien. Merci
Alif
12
public static void hideSoftKeyboard(Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager)  activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}

après cet appel sur onTouchListener:

findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Utils.hideSoftKeyboard(activity);
        return false;
    }
});
Sagar Maiyad
la source
Essayez aussi ceci - cela a fonctionné pour moi: InputMethodManager imm = ((InputMethodManager) getSystemService (Activity.INPUT_METHOD_SERVICE)); imm.hideSoftInputFromWindow (getWindow (). getCurrentFocus (). getWindowToken (), 0);
zmicer
12

utilisez ceci

this.getWindow().setSoftInputMode(
            WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Atish Agrawal
la source
12

Pour mon cas, j'utilisais le SearchView dans la barre d'actions. Après qu'un utilisateur a effectué une recherche, le clavier s'ouvrirait à nouveau.

L'utilisation de InputMethodManager n'a pas fermé le clavier. J'ai dû effacer Focus et définir le focusable de la vue de recherche sur false:

mSearchView.clearFocus();
mSearchView.setFocusable(false);
tommy chheng
la source
1
Très intelligent. Si l'utilisateur souhaite une autre recherche, cliquez à nouveau sur Rechercher.
Alex
SearchView n'en a pas clearFocus()dans les pages d'API Android, donc cela n'a pas fonctionné pour moi, mais une autre solution l'a fait (voir ma réponse ci-dessous).
Azurespot
@Noni A, stackoverflow.com/questions/7409288/…
Yousha Aleayoub
12

J'ai le cas, où mon EditTextpeut être situé également dans un AlertDialog, donc le clavier doit être fermé en cas de 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 );
}
78%
la source
1
Cette solution est meilleure car vous ne devez pas contrôler le passage de EditText en tant que paramètre à la méthode hideSoftInputFromWindow (). Cela fonctionne très bien !!
Billyjoker
12

J'ai presque essayé toutes ces réponses, j'ai eu des problèmes aléatoires, en particulier avec le Samsung Galaxy S5.

Je finis par forcer le show et le hide, et cela fonctionne parfaitement:

/**
 * Force show softKeyboard.
 */
public static void forceShow(@NonNull Context context) {
    InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}

/**
 * Force hide softKeyboard.
 */
public static void forceHide(@NonNull Activity activity, @NonNull EditText editText) {
    if (activity.getCurrentFocus() == null || !(activity.getCurrentFocus() instanceof EditText)) {
        editText.requestFocus();
    }
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
    activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
}
ahmed_khan_89
la source