2011-02-07 5 views
1

Dans mon application, je veux afficher une liste de choses et fournir à l'utilisateur la possibilité de filtrer la liste en utilisant le clavier virtuel. À cette fin, j'ai ajouté un bouton qui devrait déclencher (cacher/afficher) le clavier logiciel pour le filtrage. Je ne veux pas avoir un contrôle de texte d'édition visible, car cela prendrait de l'espace inutile. Plutôt que cela, je voudrais afficher un toast montrant la requête de filtre que l'utilisateur tape, tout comme l'attribut 'android: textFilterEnabled' pour ListView. À ma connaissance, il n'y a pas de façon évidente de le faire avec les composants Android disponibles. J'ai donc essayé l'approche suivante:android: problèmes avec l'invocation programmatique du clavier logiciel

1) la création d'une mise en page contenant du texte d'édition invisible et la vue de la liste:

<ListView android:id="@+id/main_list" 
      android:drawSelectorOnTop="false" 
      android:layout_height="0px" 
      android:layout_width="fill_parent" 
      android:layout_weight="5" 
      /> 

2) bouton ajouter dans une fenêtre contextuelle et appelant InputMethodManager lorsque vous cliquez pour basculer l'entrée logique (appelée dans onCreate):

private void initButton() { 
    Button buttonView = (Button) getLayoutInflater().inflate(R.layout.keyboard_button, null); 
    buttonView.setOnClickListener(new View.OnClickListener() { 
     public void onClick(View v) { 
      final View target = findViewById(R.id.filterbox); 
      InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 
      // this does not work... 
      // imm.toggleSoftInputFromWindow(target.getWindowToken(), InputMethodManager.SHOW_FORCED, 0); 
      // ... so need to track this in an instance variable - which sucks 
      if (imeShowing) { 
       imm.hideSoftInputFromWindow(target.getWindowToken(), 0); 
       imeShowing = false; 
      } else { 
       // check that the filterbox got focus 
       Preconditions.checkState(target.requestFocusFromTouch()); 
       Preconditions.checkState(target.hasWindowFocus()); 
       Preconditions.checkState(target.hasFocus()); 
       imm.showSoftInput(target, 0); 
       imeShowing = true; 
      } 
     } 
    }); 
    buttonPopup = new PopupWindow(buttonView); 
    // ... code to display the button as a small popup 
} 

Comme mentionné dans l'exemple de code, l'approche «évidente» (en appelant toggleSoftInput) ne fonctionne pas, donc j'ai dû revenir à cette moche if-else. Ceci est cependant un problème secondaire. Le problème principal est que lorsque je lance ceci dans l'émulateur, le clavier logiciel est affiché correctement, mais dès que je commence à le saisir, les systèmes commencent une intention pour l'activité de recherche google! Et les caractères tapés apparaissent dans le champ de recherche Google affiché comme résultat. Ce qui est encore plus bizarre, cela ne se produit que la première fois que je tape après le déploiement et l'exécution de l'application. C'est à dire. si je retourne à mon application à partir du champ de recherche Google, tout fonctionne comme prévu (pas de redirections vers le champ de recherche). Avant de montrer l'affichage je m'assure que l'edittext invisible obtient le focus, donc devrait être être la cible du clavier doux, non?

Est-ce que quelqu'un a une idée de ce qui se passe ici?

+0

Ok, j'ai compris que cela avait à voir avec le fait que le bouton est dans une fenêtre contextuelle. Lorsque je place le bouton dans la fenêtre de l'activité (où se trouvent la liste et la boîte de filtre), tout fonctionne correctement. On dirait qu'il y a un problème avec la fenêtre actuellement focalisée (quand le bouton est pressé, la fenêtre focalisée est évidemment la fenêtre et j'essaye de la commuter par programmation à la fenêtre d'activité, qui pour une raison quelconque ne fonctionne pas). – kordzik

+0

Il existe également une meilleure façon d'implémenter le filtrage de clavier virtuel - tout ce qui doit être fait est d'afficher le clavier logiciel, de se concentrer sur la vue de liste et de fournir un filtre personnalisé à son adaptateur.La pièce manquante est comment la faire fonctionner à travers deux fenêtres, je vais essayer de comprendre cela – kordzik

Répondre

1

Désolé, ce moi est (l'auteur de cette question), je ne peux pas accéder à mon ancien compte en raison de SO nouvelle connexion OpenID « awesome »:/

Je compris que ce que je dois vraiment faire est juste activer l'attribut 'android: textFilterEnabled' de la liste, et se concentrer sur le clic du bouton. ListView prend en charge l'entrée à partir du clavier logiciel (bien que je l'ai compris en regardant le code réel de AbsListView plutôt que d'obtenir des conseils dans toute la documentation :). En outre, j'ai réussi à faire fonctionner PopupWindow pour le bouton (au lieu de Dialog que j'ai essayé précédemment) de sorte que le problème de mise au point est parti. Le code de travail pour ce (au cas où quelqu'un a un problème similaire) ci-dessous:

View popupView = getLayoutInflater().inflate(R.layout.keyboard_button, null); 
Button buttonView = (Button) popupView.findViewById(R.id.keyboardButton); 
buttonView.setOnClickListener(new View.OnClickListener() { 
    public void onClick(View v) { 
     InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 
     final View list = findViewById(R.id.the_list); 
     list.requestFocus(); 
     imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); 
    } 
}); 
buttonPopup = new PopupWindow(this); 

La liste se chargera de saisie au clavier souple comme il le fait d'un disque. L'astuce consiste simplement à déclencher le clavier et à se concentrer sur la liste. Vous pouvez également contrôler comment le filtrage est appliqué à la liste en définissant un QueryFilterProvider personnalisé sur son adaptateur associé.

Questions connexes