Ok, tout le monde sait que pour masquer un clavier, vous devez implémenter:
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
Mais le gros problème ici est de savoir comment masquer le clavier lorsque l'utilisateur touche ou sélectionne un autre endroit qui n'est pas un EditText
ou le softKeyboard?
J'ai essayé d'utiliser le onTouchEvent()
sur mon parent, Activity
mais cela ne fonctionne que si l'utilisateur touche en dehors de toute autre vue et qu'il n'y a pas de défilement.
J'ai essayé d'implémenter un écouteur tactile, clic, focus sans succès.
J'ai même essayé d'implémenter ma propre vue de défilement pour intercepter les événements tactiles, mais je ne peux obtenir que les coordonnées de l'événement et non la vue cliquée.
Existe-t-il un moyen standard de le faire ?? dans l'iPhone, c'était vraiment facile.
la source
getFields()
ici: stackoverflow.com/questions/7790487/…Réponses:
L'extrait suivant masque simplement le clavier:
Vous pouvez mettre cela dans une classe utilitaire, ou si vous le définissez dans une activité, évitez le paramètre d'activité ou appelez
hideSoftKeyboard(this)
.La partie la plus délicate est de savoir quand l'appeler. Vous pouvez écrire une méthode qui réitère chaque étape
View
de votre activité, et vérifier si c'est uninstanceof EditText
si ce n'est pas enregistrer unsetOnTouchListener
dans ce composant et tout se mettra en place. Si vous vous demandez comment faire, c'est en fait assez simple. Voici ce que vous faites, vous écrivez une méthode récursive comme la suivante, en fait, vous pouvez l'utiliser pour faire n'importe quoi, comme configurer des polices de caractères personnalisées, etc. Voici la méthodeC'est tout, appelez simplement cette méthode après vous
setContentView
dans votre activité. Dans le cas où vous vous demandez quel paramètre vous passeriez, c'est celuiid
du conteneur parent. Attribuez unid
à votre conteneur parent comme<RelativeLayoutPanel android:id="@+id/parent"> ... </RelativeLayout>
et appeler
setupUI(findViewById(R.id.parent))
, c'est tout.Si vous souhaitez l'utiliser efficacement, vous pouvez créer une extension
Activity
et insérer cette méthode, et faire en sorte que toutes les autres activités de votre application étendent cette activité et l'appellentsetupUI()
dans laonCreate()
méthode.J'espère que cela aide.
Si vous utilisez plus d'une activité, définissez l'ID commun à la disposition parent comme
<RelativeLayout android:id="@+id/main_parent"> ... </RelativeLayout>
Ensuite, étendez une classe à partir de
Activity
et définissezsetupUI(findViewById(R.id.main_parent))
Dans sonOnResume()
et étendez cette classe au lieu de `` Activitéin your program
Voici une version Kotlin de la fonction ci-dessus:
la source
if(activity.getCurrentFocus() != null) {...}
OnTouchListener
pour elles. Vous pouvez simplement définir cette logique dans uneViewGroup.onInterceptTouchEvent(MotionEvent)
vue racine.Vous pouvez y parvenir en procédant comme suit:
Rendre la vue parent (vue de contenu de votre activité) cliquable et focalisable en ajoutant les attributs suivants
Implémenter une méthode hideKeyboard ()
Enfin, définissez le onFocusChangeListener de votre edittext.
Comme indiqué dans l'un des commentaires ci-dessous, cela peut ne pas fonctionner si la vue parent est un ScrollView. Dans ce cas, le ClickTable et le focusableInTouchMode peuvent être ajoutés sur la vue directement sous ScrollView.
la source
clickable
etfocusableInTouchMode
de monScrollView
élément racine . J'ai dû ajouter au parent direct de monEditText
qui était unLinearLayout
.Remplacez simplement le code ci-dessous dans Activity
la source
Je trouve la réponse acceptée un peu compliquée.
Voici ma solution. Ajoutez un
OnTouchListener
à votre mise en page principale, c'est-à-dire:et mettez le code suivant dans la méthode onTouch.
De cette façon, vous n'avez pas à parcourir toutes les vues.
la source
android:onClick="stealFocusFromEditTexts"
au xml de la vue parent puispublic void stealFocusFromEditTexts(View view) {}
à son activité. La méthode au clic n'a rien à faire, elle doit simplement exister pour que la vue parent soit focalisable / sélectionnable, ce qui est nécessaire pour voler le focus à l'enfant EditTextJ'ai une autre solution pour masquer le clavier:
Ici, passez
HIDE_IMPLICIT_ONLY
à la positionshowFlag
et0
à la position dehiddenFlag
. Il fermera de force le clavier virtuel.la source
Eh bien, je parviens à résoudre quelque peu le problème, j'ai outrepassé le dispatchTouchEvent sur mon activité, là j'utilise ce qui suit pour masquer le clavier.
ÉDITER: La méthode getFields () est juste une méthode qui retourne un tableau avec les champs de texte dans la vue. Pour éviter de créer ce tableau à chaque contact, j'ai créé un tableau statique appelé sFields, qui est renvoyé par la méthode getFields (). Ce tableau est initialisé sur les méthodes onStart () telles que:
sFields = new EditText[] {mUserField, mPasswordField};
Ce n'est pas parfait, le temps de l'événement glisser n'est basé que sur l'heuristique, donc parfois il ne se cache pas lors de l'exécution de longues clics, et j'ai également fini par créer une méthode pour obtenir tous les editTexts par vue; sinon le clavier se cacherait et s'afficherait en cliquant sur un autre EditText.
Pourtant, des solutions plus propres et plus courtes sont les bienvenues
la source
getFields()
méthode? Il ne doit pas être exact, juste un exemple avec peut-être juste quelques commentaires indiquant qu'il retourne un tableau d'EditText
objets.Utilisez OnFocusChangeListener .
Par exemple:
Mise à jour : vous pouvez également remplacer
onTouchEvent()
votre activité et vérifier les coordonnées du toucher. Si les coordonnées sont en dehors de EditText, masquez le clavier.la source
J'ai implémenté dispatchTouchEvent dans Activity pour ce faire:
et je l'ai testé, fonctionne parfaitement!
la source
Une manière plus Kotlin & Material Design en utilisant TextInputEditText (cette approche est également compatible avec EditTextView ) ...
1.Rendez la vue parent (vue du contenu de votre activité / fragment) cliquable et focalisable en ajoutant les attributs suivants
2.Créez une extension pour toutes les vues (dans un fichier ViewExtension.kt par exemple):
3.Créez un BaseTextInputEditText héritant de TextInputEditText. Implémentez la méthode onFocusChanged pour masquer le clavier lorsque la vue n'est pas focalisée:
4.Appelez simplement votre nouvelle vue personnalisée dans votre XML:
C'est tout. Pas besoin de modifier vos contrôleurs (fragment ou activité) pour gérer ce cas répétitif.
la source
Remplacer le booléen public dispatchTouchEvent (événement MotionEvent) dans n'importe quelle activité (ou étendre la classe d'activité)
Et c'est tout ce que vous devez faire
la source
J'ai modifié la solution d'Andre Luis IM J'ai réalisé celle-ci:
J'ai créé une méthode utilitaire pour masquer le clavier virtuel de la même manière qu'André Luiz IM:
Mais au lieu d'enregistrer un OnTouchListener pour chaque vue, qui donne une mauvaise performance, j'ai enregistré le OnTouchListener pour juste la vue racine. Puisque l'événement bouillonne jusqu'à ce qu'il soit consommé (EditText est l'une des vues qui le consomme par défaut), s'il arrive à la vue racine, c'est parce qu'il n'a pas été consommé, donc je ferme le clavier virtuel.
la source
Je suis conscient que ce fil est assez ancien, la bonne réponse semble valide et il existe de nombreuses solutions de travail, mais je pense que l'approche indiquée ci-dessous pourrait avoir un avantage supplémentaire en termes d'efficacité et d'élégance.
J'ai besoin de ce comportement pour toutes mes activités, j'ai donc créé une classe CustomActivity héritant de la classe Activity et "accroché" la fonction dispatchTouchEvent . Il y a principalement deux conditions à respecter:
Voici mon résultat:
Note latérale: De plus, j'attribue ces attributs à la vue racine, ce qui permet d'effacer le focus sur chaque champ de saisie et d'empêcher les champs de saisie de se concentrer sur le démarrage de l'activité (faisant de la vue du contenu le "capteur de focus"):
la source
J'ai aimé l'approche d'appels
dispatchTouchEvent
faite par htafoya, mais:J'ai donc rendu cette solution un peu plus simple:
Il y a un inconvénient:
Le passage de l'un
EditText
à l'autreEditText
rend le clavier masqué et reshow - dans mon cas, c'est souhaité de cette façon, car cela montre que vous avez basculé entre deux composants d'entrée.la source
Plaidoyer: Je reconnais que je n'ai aucun poids, mais veuillez prendre ma réponse au sérieux.
Problème: Ignorez le clavier logiciel lorsque vous cliquez en dehors du clavier ou modifiez le texte avec un code minimal.
Solution: bibliothèque externe connue sous le nom de Butterknife.
Solution en une ligne:
Solution plus lisible:
Explication: Liez l'écouteur OnClick à l'ID parent de la disposition XML de l'activité, de sorte que tout clic sur la disposition (et non sur le texte ou le clavier d'édition) exécutera cet extrait de code qui masquera le clavier.
Exemple: si votre fichier de mise en page est R.layout.my_layout et votre ID de mise en page est R.id.my_layout_id, votre appel de liaison Butterknife devrait ressembler à:
Lien de documentation de Butterknife: http://jakewharton.github.io/butterknife/
Plug: Butterknife va révolutionner votre développement Android. Considère-le.
Remarque: Le même résultat peut être obtenu sans l'utilisation de la bibliothèque externe Butterknife. Définissez simplement un OnClickListener sur la disposition parent comme décrit ci-dessus.
la source
En kotlin, nous pouvons faire ce qui suit. Pas besoin d'itérer toutes les vues. Cela fonctionnera également pour les fragments.
la source
Voici une autre variante de la réponse de fje qui répond aux problèmes soulevés par sosite.
L'idée ici est de gérer à la fois les actions vers le bas et vers le haut dans les activités
dispatchTouchEvent
méthode de . Sur l'action vers le bas, nous prenons note de la vue actuellement focalisée (le cas échéant) et si le toucher était à l'intérieur, en enregistrant ces deux informations pour plus tard.Sur l'action ascendante, nous envoyons d'abord, pour permettre à une autre vue de prendre potentiellement le focus. Si après cela, la vue actuellement mise au point est la vue initialement mise au point et que le toucher vers le bas était à l'intérieur de cette vue, alors nous laissons le clavier ouvert.
Si la vue actuellement focalisée est différente de la vue initialement focalisée et que c'est un
EditText
, alors nous laissons également le clavier ouvert.Sinon, nous le fermons.
Donc, pour résumer, cela fonctionne comme suit:
EditText
, le clavier reste ouvertEditText
à un autreEditText
, le clavier reste ouvert (ne se ferme pas / ne se rouvre pas)EditText
qui n'est pas un autreEditText
, le clavier se fermeEditText
pour faire apparaître la barre d'action contextuelle (avec les boutons couper / copier / coller), le clavier reste ouvert, même si l'action UP s'est déroulée en dehors du focusEditText
(qui s'est déplacée vers le bas pour faire de la place pour le CAB) . Notez, cependant, que lorsque vous appuyez sur un bouton dans le CAB, il fermera le clavier. Cela peut être souhaitable ou non; si vous voulez couper / copier d'un champ et coller dans un autre, ce serait le cas. Si vous souhaitez coller à nouveau dans le mêmeEditText
, ce ne serait pas.lorsque le focus
EditText
est en bas de l'écran et que vous cliquez longuement sur du texte pour le sélectionner, leEditText
focus reste et donc le clavier s'ouvre comme vous le souhaitez, car nous faisons le "toucher est dans les limites de la vue" vérifier l'action vers le bas , pas l'action up.la source
c'est trop simple, il suffit de rendre votre mise en page récente cliquable et focalisable par ce code:
puis écrivez une méthode et un OnClickListner pour cette disposition, de sorte que lorsque la disposition la plus élevée est touchée, elle appelle une méthode dans laquelle vous écrivez du code pour ignorer le clavier. voici le code pour les deux; // vous devez écrire ceci dans OnCreate ()
méthode appelée depuis listner: -
la source
Je trouve le bit de réponse accepté complexe pour cette simple exigence. Voici ce qui a fonctionné pour moi sans aucun problème.
la source
NestedScrollView
des mises en page complexes ou complexes, consultez la réponse acceptée: stackoverflow.com/a/11656129/2914140 . Vous devez savoir que d'autres conteneurs peuvent consommer des touches.Il existe une approche plus simple, basée sur le même problème avec l'iPhone. Remplacez simplement la disposition de l'arrière-plan lors de l'événement tactile, où le texte d'édition est contenu. Utilisez simplement ce code dans OnCreate de l'activité (login_fondo est la disposition racine):
la source
Méthode pour afficher / masquer le clavier logiciel
J'espère qu'ils ont été utiles
la source
Celui-ci est la solution la plus simple pour moi (et élaborée par moi).
Il s'agit de la méthode pour masquer le clavier.
définissez maintenant l'attribut onclick de la disposition parent de l'activité sur la méthode ci-dessus à
hideKeyboard
partir du mode Création de votre fichier XML ou en écrivant le code ci-dessous en mode Texte de votre fichier XML.la source
J'ai affiné la méthode, mis le code suivant dans une classe d'utilitaire d'interface utilisateur (de préférence, pas nécessairement) afin qu'il puisse être consulté à partir de toutes vos classes d'activité ou de fragment pour servir son objectif.
Dites ensuite par exemple que vous devez l'appeler depuis l'activité, appelez-la comme suit;
Remarquer
Cela nous donne la vue racine du groupe actuel (vous ne devez pas avoir défini l'identifiant sur la vue racine).
À votre santé :)
la source
Essayez de mettre stateHidden comme
windowSoftInputMode
valeur d' activitéhttp://developer.android.com/reference/android/R.attr.html#windowSoftInputMode
Par exemple pour votre activité:
la source
Activité
ScreenUtils
la source
Ajoutez simplement ce code dans la classe @Overide
la source
Au lieu d'itérer dans toutes les vues ou de remplacer dispatchTouchEvent.
Pourquoi ne pas simplement remplacer onUserInteraction () de l'activité, cela garantira que le clavier sera ignoré chaque fois que l'utilisateur tapera en dehors de EditText.
Fonctionne même lorsque EditText est à l'intérieur de scrollView.
la source
Je l'ai fait fonctionner avec une légère variante de la solution de Fernando Camarago. Dans ma méthode onCreate, j'attache un seul onTouchListener à la vue racine mais envoie la vue plutôt que l'activité comme argument.
Dans une classe d'Utils séparée est ...
la source
Cela peut être ancien, mais j'ai réussi à le faire en impliquant une classe personnalisée
la meilleure pratique consiste à créer une classe d'assistance et chaque disposition relative / linéaire des conteneurs doit l'implémenter.
**** Notez que seul le conteneur principal doit implémenter cette classe (pour l'optimisation) ****
et l'implémenter comme ceci:
le mot-clé c'est pour l'activité. donc si vous êtes sur un fragment que vous utilisez comme getActivity ();
--- bravo si ça vous aide ... --- bravo Ralph ---
la source
Il s'agit d'une version légèrement modifiée de la réponse de fje qui fonctionnait pour la plupart parfaitement.
Cette version utilise ACTION_DOWN, donc effectuer une action de défilement ferme également le clavier. Il ne propage pas non plus l'événement sauf si vous cliquez sur un autre EditText. Cela signifie que cliquer n'importe où en dehors de votre EditText, même sur un autre cliquable, ferme simplement le clavier.
la source
view
etviewTmp
àgetCurrentFocus()
, donc ils auront toujours la même valeur.J'ai fait comme ça:
Masquer le code du clavier :
Terminé
la source