Tout d'abord, vous devez créer une mise en page XML qui contient à la fois un EditText et un ListView.
Cela disposera tout correctement, avec un joli EditText au-dessus du ListView. Ensuite, créez une ListActivity comme vous le feriez normalement, mais ajoutez un appel setContentView()
dans la méthode onCreate()
afin d'utiliser notre mise en page récemment déclarée. Rappelez-vous que nous avons spécialement identifié le ListView
avec android:id="@android:id/list"
. Cela permet à la ListActivity de savoir quel 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(this,
android.R.layout.simple_list_item_1,
getStringArrayList());
}
Maintenant, en exécutant l'application, vous devriez voir votre ListView précédent, avec une jolie boîte au-dessus. Pour que cette boîte fasse quelque chose, nous devons prendre l'entrée et filtrer la liste. Alors que beaucoup de gens ont essayé de le faire manuellement, la plupart des classes d'adaptateur ListView viennent avec un objet Filter qui peut être utilisé pour effectuer le filtrage automatiquement. Nous devons simplement rediriger l'entrée de l'EditText vers le Filter. Il s'avère que c'est assez facile. Pour faire un test rapide, ajoutez cette ligne à votre appel onCreate()
adapter.getFilter().filter(s);
Remarquez que vous devrez enregistrer votre ListAdapter dans une variable pour que cela fonctionne - j'ai sauvegardé mon ArrayAdapter précédent dans une variable appelée 'adapter'.
La prochaine étape consiste à obtenir l'entrée de l'EditText. Cela nécessite un peu de réflexion. Vous pourriez ajouter un OnKeyListener à votre EditText. Cependant, cet auditeur ne reçoit que certains événements de touches. Par exemple, si un utilisateur entre 'wyw', le texte prédictif recommandera probablement 'œil'. Jusqu'à ce que l'utilisateur choisisse soit 'wyw' soit 'œil', votre OnKeyListener ne recevra pas d'événement de touche. Certains peuvent préférer cette solution, mais je l'ai trouvée frustrante. Je voulais chaque événement de touche, pour avoir le choix de filtrer ou non. La solution est un TextWatcher. Créez simplement et ajoutez un TextWatcher à l'EditText, et transmettez une demande de filtrage au Filter de ListAdapter à chaque changement de texte. N'oubliez pas de supprimer le TextWatcher dans OnDestroy ! Voici la solution finale :
private EditText filterText = null;
ArrayAdapter 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(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);
}