web-dev-qa-db-fra.com

Comment mettre à jour dynamiquement un ListView sur Android

Sous Android, comment puis-je utiliser un ListView qui filtre en fonction des entrées de l'utilisateur, les éléments affichés étant mis à jour de manière dynamique en fonction de la valeur TextView?

Je cherche quelque chose comme ça:

-------------------------
| Text View             |
-------------------------
| List item             |
| List item             |
| List item             |
| List item             |
|                       |
|                       |
|                       |
|                       |
-------------------------
159
Hamy

Tout d'abord, vous devez créer une mise en page XML comportant à 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>

Cela mettra tout en place correctement, avec un Nice EditText au-dessus de ListView. Ensuite, créez une ListActivity comme vous le feriez normalement, mais ajoutez un appel setContentView() dans la méthode onCreate() afin que nous utilisions notre layout récemment déclaré. Rappelez-vous que nous avons identifié le ListView spécialement, avec Android:id="@Android:id/list". Ceci permet au ListActivity de savoir quel ListView nous voulons utiliser dans notre présentation 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());
    }

Lancer l'application maintenant devrait montrer votre précédent ListView, avec une belle boîte ci-dessus. Pour que cette boîte de dialogue fasse quelque chose, nous devons prendre son entrée et lui faire filtrer la liste. Bien que beaucoup de gens aient essayé de le faire manuellement, les classes la plupartListViewAdapter sont fournies avec un objet Filter qui peut être utilisé pour effectuer les opérations suivantes: filtrer automatiquement. Nous avons juste besoin de canaliser l'entrée du EditText dans le Filter. Il s'avère que c'est assez facile. Pour exécuter un test rapide, ajoutez cette ligne à votre appel onCreate()

adapter.getFilter().filter(s);

Notez que vous aurez besoin de sauvegarder votre ListAdapter dans une variable pour que cela fonctionne. J'ai sauvegardé mon ArrayAdapter<String> Précédemment dans une variable appelée "adaptateur".

La prochaine étape consiste à obtenir les données de EditText. Cela prend un peu de réflexion. Vous pouvez ajouter une 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 n'aura pas choisi 'wyw' ou 'eye', votre OnKeyListener ne recevra pas d'événement de clé. Certains préfèrent peut-être cette solution, mais je l’ai trouvée frustrante. Je voulais chaque événement clé, donc j'avais le choix de filtrer ou non. La solution est un TextWatcher. Il vous suffit de créer et d'ajouter un TextWatcher au EditText et de transmettre le ListAdapterFilter une demande de filtre à chaque changement de texte. N'oubliez pas de supprimer le TextWatcher dans 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);
}
286
Hamy

l'exécution du programme provoquera une fermeture forcée.

J'ai échangé la ligne:

Android: id = "@ + building_list/search_box"

avec

Android: id = "@ + id/search_box"

est-ce que cela pourrait être le problème? A quoi sert '@ + building_list'?

10
j7nn7k

j'ai eu un problème avec le filtrage, les résultats ont été filtrés, mais non restauré!

donc avant de filtrer (début d'activité) j'ai créé une sauvegarde de liste .. (juste une autre liste, contenant les mêmes données)

lors du filtrage, le filtre et l'adaptateur de liste sont connectés à la liste primaire.

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

dans mon cas, cela garantissait que la liste était mise à jour immédiatement et même après suppression des caractères de recherche-terme, la liste était restaurée avec succès dans tous les cas :)

merci pour cette solution quand même.

4
cV2