Question

Sur Android, comment puis-je un ListView que des filtres basés sur l'entrée de l'utilisateur, où les éléments affichés sont mis à jour dynamiquement en fonction de la valeur de TextView?

Je cherche quelque chose comme ceci:

-------------------------
| Text View             |
-------------------------
| List item             |
| List item             |
| List item             |
| List item             |
|                       |
|                       |
|                       |
|                       |
-------------------------
Était-ce utile?

La solution

D'abord, vous devez créer une mise en page XML qui a à la fois un EditText et un ListView.

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <!-- Pretty hint text, and maxLines -->
    <EditText android:id="@+building_list/search_box" 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="type to filter"
        android:inputType="text"
        android:maxLines="1"/>

    <!-- Set height to 0, and let the weight param expand it -->
    <!-- Note the use of the default ID! This lets us use a 
         ListActivity still! -->
    <ListView android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="0dip"
        android:layout_weight="1" 
         /> 

</LinearLayout>

pondra tout correctement, avec un EditText bien au-dessus du ListView. Ensuite, créez un ListActivity comme vous le feriez normalement, mais ajouter un appel setContentView() dans la méthode onCreate() nous utilisons donc notre disposition récemment déclarée. Rappelez-vous que nous ID'ed le ListView spécialement, avec android:id="@android:id/list". Cela permet au ListActivity de savoir quels ListView nous voulons utiliser dans notre mise en page déclarée.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.filterable_listview);

        setListAdapter(new ArrayAdapter<String>(this,
                       android.R.layout.simple_list_item_1, 
                       getStringArrayList());
    }

L'exécution de l'app devrait montrer votre ListView précédente, avec une jolie boîte ci-dessus. Afin de rendre cette boîte faire quelque chose, nous devons prendre l'entrée de celui-ci, et faire cette entrée filtrer la liste. Alors que beaucoup de gens ont essayé de le faire manuellement, la plupart ListView classes Adapter viennent avec un objet Filter qui peut être utilisé pour effectuer automagiquement le filtrage. Nous avons juste besoin de tuyau l'entrée du EditText dans le Filter. Transforme que est assez facile. Pour exécuter un test rapide, ajoutez cette ligne à votre appel onCreate()

adapter.getFilter().filter(s);

Notez que vous devez enregistrer votre ListAdapter à une variable pour faire ce travail -. Je l'ai sauvé ArrayAdapter<String> de plus tôt dans une variable appelée « adaptateur »

L'étape suivante consiste à obtenir l'entrée du EditText. Cela prend en fait un peu de réflexion. Vous pouvez ajouter un OnKeyListener() à votre EditText. Cependant, cet écouteur ne reçoit que certains événements clés . Par exemple, si un utilisateur entre « WYW », le texte prédictif recommandera probablement « œil ». Tant que l'utilisateur choisit soit « WYW » ou « œil », votre OnKeyListener ne recevra pas un événement clé. Certains peuvent préférer cette solution, mais je l'ai trouvé frustrant. Je voulais que chaque événement clé, donc j'eu le choix de filtrage ou non filtrage. La solution est un TextWatcher. Il suffit de créer et ajouter un TextWatcher au EditText, et passer le ListAdapter Filter une demande de filtre à chaque fois que le texte change. Rappelez-vous de retirer le TextWatcher en OnDestroy()! Voici la solution finale:

private EditText filterText = null;
ArrayAdapter<String> adapter = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.filterable_listview);

    filterText = (EditText) findViewById(R.id.search_box);
    filterText.addTextChangedListener(filterTextWatcher);

    setListAdapter(new ArrayAdapter<String>(this,
                   android.R.layout.simple_list_item_1, 
                   getStringArrayList());
}

private TextWatcher filterTextWatcher = new TextWatcher() {

    public void afterTextChanged(Editable s) {
    }

    public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {
    }

    public void onTextChanged(CharSequence s, int start, int before,
            int count) {
        adapter.getFilter().filter(s);
    }

};

@Override
protected void onDestroy() {
    super.onDestroy();
    filterText.removeTextChangedListener(filterTextWatcher);
}

Autres conseils

l'exécution du Programme provoquera une étroite force.

Je swaped la ligne:

  

android: id = "@ + building_list / search_box"

avec

  

android: id = "@ + id / search_box"

pourrait-il être le problème? Quel est le '@ + building_list' pour?

i eu un problème avec le filtrage, que les résultats ont été filtrés, mais non restauré

avant filtrage (début d'activité) i créé une sauvegarde de la liste .. (Juste une autre liste, contenant les mêmes données)

sur le filtrage, le filtre et listadapter est reliée à la liste primaire.

mais le filtre lui-même utilisé les données de la liste Backupées.

assuré dans mon cas, que la liste a été immédiatement mis à jour et même sur la suppression de caractères-terme-recherche la liste est restaurée avec succès dans tous les cas:)

Merci pour cette solution de toute façon.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top