Mon problème est simple. Comment Effacer le focus de tous les éléments d'une vue pouvant avoir le focus ( like EditText
-or- TextView
dont textIsSelectable="true"
et le texte y sont sélectionnés à l'occurrence de l'événement clearFocus ).
Pourquoi je demande (au cas où je ne recevrais pas de réponse générique ci-dessus):
J'ai quelques fragments auxquels j'accède via Vue de navigation . Mon objectif principal est de perdre la focalisation des éléments du fragment sur Drawer open in Navigation View. Je sais qu’il est possible d’obtenir la méthode onDrawerSlide
pour NavigationDrawer et de l’avoir configurée dans mon MainActivity afin que, dans le tiroir ouvert, si mon EditText dans un des fragments soit ouvert, j’appelle le code hideSoftKeyboard de sorte à fermer le SoftKeyboard.
Mon code pour obtenir l'événement à l'ouverture du tiroir : (dans la méthode onCreate () de MainActivity)
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
{
//Hide SoftKeyboard on Navigation Drawer Open
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
//Hide SoftKeyboard if it is open
hideSoftKeyboard();
//And Make any view having focus loose focus
//...
//ClearFocus for the whole view is done from here (for whichever Fragment is visible right now)
super.onDrawerSlide(drawerView, slideOffset);
}
};
public void hideSoftKeyboard() //Declared outside onCreate
{
InputMethodManager inputMethodManager = (InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
Ici, mon code hideSoftKeyboard () est generic et peut fermer SoftKeyboard quel que soit le fragment visible à l’instant depuis MainActivity lui-même . De même Je veux clearFocus de tous mes EditTexts et TextView (puisque l’option Copier/Coller s’affiche au milieu du tiroir quand il est ouvert).
Je sais que je peux écrire du code pour chaque fragment appelant la fonction onDrawerSlide et effaçant le focus de chaque élément individuellement, mais je veux savoir s’il est possible de trouver une solution générique et, dans l’affirmative, comment le faire.
(Si cela est possible, cela pourrait avoir de nombreuses implications et aider dans de nombreux cas)
Enfin, j’ai finalement décidé que je ne pouvais pas attendre plus longtemps pour une réponse générale et j’ai donc décidé d’appliquer la variable onDrawerSlide
pour chaque fragment . En fin de compte, même si cela reste un peu délicat, vous devez accéder à votre barre d’outils et configurer votre tiroir à l’aide du tiroir actuel, et un peu d’expérience a fait jaillir NPE! (Juste ma chance habituelle)
Il en allait de même pour le site officiel des développeurs Android, qui m'a éclairé. Pourquoi ne pas utiliser getCurrentFocus
pour obtenir ma vue actuelle puis clearFocus()
! Et voila, ça marche. Je me concentrais tellement sur la situation complexe que j'ai oublié de vérifier les parties les plus faciles.
Alors voici la réponse à ma propre question: (dans onCreate for MainActivity)
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
{
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
hideSoftKeyboard();
getCurrentFocus().clearFocus(); //clear focus - any view having focus
super.onDrawerSlide(drawerView, slideOffset);
}
Merci à @keivan Esbati pour avoir signalé une échappatoire que je n’avais pas remarquée en raison de mon utilisation de la vue factice (utilisé dans layout xml afin que, dès que Layout soit chargé, le premier EditText n’obtient pas le focus). Selon le forum des développeurs Android:
clearFocus (): Quand une vue efface le focus, le cadre tente de focaliser sur la première vue focalisable vue du haut. Par conséquent, si cette vue est la première vue du haut. Qui peut prendre le focus, tous les rappels liés à la mise au point de Seront invoqués, après quoi le cadre donnera à Le focus sur cette vue.
Pour contourner ce problème, il est bien sûr de configurer une variable factice qui appelle le focus dès que Layout est chargé (méthode que j'ai utilisée) ou this partagé par @keivan.
_ {Remarque: j'avais mis une prime pour cela, car personne n'était capable de répondre et j'ai moi-même la réponse, je me demande ce qu'il adviendra du Bounty} _: D
_ {Mise à jour: Bounty a expiré et euh, il ne s'est rien passé. Je suppose que cela a du sens si vous utilisez la théorie de la publicité.} _
Pour effacer le focus d'une vue, vous pouvez appeler getCurrentFocus().clearFocus()
. N'oubliez toutefois pas que cela déplace simplement le focus de la vue actuelle sur le premier élément de votre vue, sans supprimer complètement le focus des vues. Donc, si le premier élément de votre mise en page est une EditText
, il sera de nouveau ciblé.
Un moyen de vous assurer que votre vue ne sera plus focalisée consiste à ajouter ces attributs à votre vue racine dans votre fichier xml, permettant ainsi à la vue racine de capturer le focus:
Android:focusableInTouchMode="true"
Android:descendantFocusability="beforeDescendants"
Donc, si vous déclarez votre élément racine comme ci-dessous, il va automatiquement capter le focus avant d'atteindre les vues enfant:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:focusableInTouchMode="true"
Android:descendantFocusability="beforeDescendants">
<!-- Rest of Layout -->
<.../>
</LinearLayout>
Si vous avez plusieurs activités et que dans ces activités une seule activité, vous disposez de la vue Navigation. Dans ce cas, si vous souhaitez effacer le focus sur navView, utilisez ce code,
@Override
protected void onResume() {
super.onResume();
int size = navigationView.getMenu().size();
for (int i = 0; i < size; i++) {
navigationView.getMenu().getItem(i).setChecked(false);
}
}