tablette - Fermer/cacher le clavier virtuel Android




masquer clavier virtuel android (20)

J'ai un EditText et un Button dans ma mise en page.

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


La réponse courte

Dans votre écouteur OnClick appelez onEditorAction de EditText avec IME_ACTION_DONE

button.setOnClickListener(new OnClickListener() {

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

Le forage

Je pense que cette méthode est meilleure, plus simple et plus alignée sur 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 le focus et c’est également celui qui EditText le clavier en premier lieu (il est certainement capable de l’invoquer de nombreux scénarios courants). De la même manière, ce devrait être celui qui ImeAction 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 obtenir le même comportement par les mêmes moyens.

Vérifiez cette réponse liée


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

J'ai encore une 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 logiciel.


J'ai passé plus de deux jours à examiner toutes les solutions affichées dans le fil de discussion et je les ai trouvées manquantes d'une manière ou d'une autre. Mon exigence exacte est d’avoir un bouton qui affiche avec une fiabilité à 100% ou masque le clavier à l’écran. Lorsque le clavier est dans son état masqué, il ne devrait pas réapparaître, quels que soient les champs de saisie sur lesquels l'utilisateur clique. Lorsqu'il est 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 RPN propre à l' application.

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

  1. Masquer temporairement le clavier. Il réapparaîtra à nouveau lorsqu'un utilisateur concentrera un nouveau champ de texte.
  2. Affichez le clavier au début d’une activité et définissez un indicateur indiquant que le clavier doit toujours être visible. Cet indicateur ne peut être défini que lorsqu’une activité est en cours d’initialisation.
  3. Marquer une activité pour ne jamais montrer ou permettre l'utilisation du clavier. Cet indicateur 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ît dès qu'un nouveau champ de texte est sélectionné. Étant donné que mon application utilise plusieurs champs de texte sur une page, la mise au point d'un nouveau champ de texte provoque la restauration du clavier masqué.

Malheureusement, les points 2 et 3 de la liste ne fonctionnent que lorsque le démarrage d’une activité est fiable. Une fois que l'activité est devenue visible, vous ne pouvez plus masquer ou afficher le clavier. L'astuce consiste à relancer 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);
    }
}

Ainsi, l’activité en cours voit son état sauvegardé dans un ensemble, puis elle est démarrée 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 logiciel doit être affiché, alors InputMethodManager est invité à afficher le clavier et la fenêtre est configurée pour que l'entrée logicielle soit toujours visible. Si le clavier logiciel doit être masqué, le paramètre WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM est défini.

Cette approche fonctionne de manière fiable sur tous les appareils que j'ai testés - d'un téléphone HTC vieux de 4 ans sous Android 2.2 à un Nexus 7 sous 4.2.2. Le seul inconvénient de cette approche est que vous devez manipuler avec soin le bouton de retour. Étant donné que mon application ne comporte quasiment qu’un seul écran (c’est une calculatrice), je peux remplacer onBackPressed () et revenir à l’écran d’accueil des appareils.


La solution de Meier fonctionne aussi pour moi. Dans mon cas, le niveau supérieur de mon application est un tabHost et je souhaite masquer le mot-clé lors du changement d'onglet. Je reçois 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);
    }
}

Pour clarifier cette folie, je voudrais commencer par m'excuser, au nom de tous les utilisateurs d'Android, du traitement carrément ridicule du clavier logiciel par Google. 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 à aucun moyen poli de le dire.

Je veux cacher le clavier. Je m'attends à fournir à Android 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 au module de gestion intégré. Maintenant nous avons un problème. Il se peut que je veuille cacher le clavier à une classe statique ou à une classe d’utilité qui n’a ni utilité ni besoin de Context . ou Pire encore, l'IMM exige que vous spécifiiez la View (ou pire, la Window ) à partir de laquelle vous voulez masquer le clavier.

C’est ce qui rend difficile de cacher le clavier. Cher Google, Lorsque je cherche la recette d’un gâteau, il n’ya aucun RecipeProvider de RecipeProvider sur Terre qui refuserait de me fournir la recette à moins que je ne réponde au préalable QUI le gâteau sera mangé par ET où il sera mangé !!

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

J'ai créé une méthode utilitaire statique qui peut effectuer le travail TRÈS solidement, à condition que vous l'appeliez à 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 d’utilité ne fonctionne UNIQUEMENT lorsque appelée à partir d’une Activity ! La méthode ci-dessus appelle getCurrentFocus de l' Activity cible pour getCurrentFocus le jeton de fenêtre approprié.

Mais supposons que vous souhaitiez masquer 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é tant que le Fragment sera affiché! Hou la la! Donc, pour cacher le clavier à des fragments, je recourt au niveau inférieur, plus commun 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 des informations supplémentaires tirées de la perte de temps supplémentaire liée à cette solution:

À propos de windowSoftInputMode

Il y a encore un autre point de discorde à prendre en compte. Par défaut, Android attribue automatiquement le focus initial au premier contrôle EditText ou EditText de votre Activity . Il s'ensuit naturellement que le InputMethod (généralement le clavier logiciel) répondra à l'événement de focus en se montrant. 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, cela ne semble en aucun cas empêcher le clavier de s'ouvrir lorsque vous appuyez sur le contrôle (sauf si focusable="false" et / ou focusableInTouchMode="false" sont attribué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 de mise au point 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.

UPDATE: Autres moyens d'obtenir un jeton de fenêtre

S'il n'y a pas de vue focalisée (par exemple, cela peut arriver 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 font pas explicitement référence à votre activité.

Dans une classe de fragments:

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

Étant donné un fragment 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: Effacez 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();


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

Créez une fonction avec qui gérera certaines propriétés d’ EditText :

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

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

Ensuite, assurez-vous que l’onFocus de EditText ouvre / ferme 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 voulez ouvrir le clavier manuellement, appelez:

setEditTextFocus(true);

Et pour la fermeture de l'appel:

setEditTextFocus(false);

Vous pouvez forcer Android à masquer le clavier virtuel à l'aide de InputMethodManager , en appelant hideSoftInputFromWindow , en transmettant 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 souhaiterez passer InputMethodManager.HIDE_IMPLICIT_ONLY en InputMethodManager.HIDE_IMPLICIT_ONLY que deuxième paramètre pour vous assurer de ne masquer le clavier que lorsque l'utilisateur ne l'a pas forcé explicitement à apparaître (en maintenant le menu enfoncé).

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


Mise à jour: Je ne sais pas pourquoi cette solution ne fonctionne plus (je viens de tester sur Android 23). Veuillez utiliser la solution de Saurabh Pareek à la place. 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);

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

Saurabh Pareek a la meilleure réponse à ce jour.

Pourriez aussi bien utiliser les drapeaux corrects, 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 ... */
}

Si vous souhaitez fermer le clavier logiciel pendant un test unitaire ou fonctionnel, vous pouvez le faire en cliquant sur le bouton "Précédent" de votre test:

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

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

Assurez-vous de faire une pause un peu avant de passer, car il faut un peu de temps pour fermer le bouton Précédent. Ainsi, les clics ultérieurs sur Vues, ​​etc., ne seront enregistrés qu'après une courte pause (une seconde est suffisamment longue). ).


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

utilisez ceci

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

Dans certains cas, ces méthodes peuvent fonctionner sauf toutes les autres. Cela sauve ma journée :)

public static void hideSoftKeyboard(Activity activity) {
    if (activity != null) {
        InputMethodManager inputManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
        if (activity.getCurrentFocus() != null && inputManager != null) {
            inputManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
            inputManager.hideSoftInputFromInputMethod(activity.getCurrentFocus().getWindowToken(), 0);
        }
    }
}

public static void hideSoftKeyboard(View view) {
    if (view != null) {
        InputMethodManager inputManager = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        if (inputManager != null) {
            inputManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
    }
}

En guise d' alternative à cette solution complète , si vous vouliez fermer le clavier logiciel de n'importe où sans disposer d'une référence au champ (EditText) utilisé pour ouvrir le clavier, tout en voulant le faire si le champ était concentré, vous pouvez utiliser ceci (d'une activité):

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

J'ai le cas, où mon EditTextpeut être situé également dans un AlertDialog, de sorte que le clavier doit être fermé sur le licenciement. 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 );
}

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 obtenir le contexte, récupérez-le auprès du constructeur :)

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

Pour mon cas, j'utilisais le SearchView dans la barre d’actions. Lorsqu'un utilisateur effectue une recherche, le clavier s'ouvre à nouveau.

L'utilisation de InputMethodManager n'a pas fermé le clavier. Je devais effacerFocus et définir la focalisation de la vue de recherche sur false:

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

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




soft-keyboard