Primeiro, você precisa criar um layout XML que tenha um EditText e um 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>
Isso organizará tudo corretamente, com um bom EditText acima do ListView. Em seguida, crie uma ListActivity como faria normalmente, mas adicione uma setContentView()
chamada no onCreate()
método para usar nosso layout declarado recentemente. Lembre-se de que identificamos o ListView
especialmente com android:id="@android:id/list"
. Isso permite que oListActivity
saber o que ListView
queremos usar em nosso layout declarado.
@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());
}
A execução do aplicativo agora deve mostrar o anterior ListView
, com uma boa caixa acima. Para fazer com que essa caixa faça alguma coisa, precisamos extrair a entrada dela e fazer com que essa entrada filtre a lista. Embora muitas pessoas tenham tentado fazer isso manualmente, a maioria das ListView
Adapter
classes vem com um Filter
objeto que pode ser usado para executar a filtragem automaticamente. Nós só precisamos canalizar a entrada do EditText
para o Filter
. Acontece que é bem fácil. Para executar um teste rápido, adicione esta linha à sua onCreate()
chamada
adapter.getFilter().filter(s);
Observe que você precisará salvar sua ListAdapter
em uma variável para fazer esse trabalho - eu salvei meuArrayAdapter<String>
anterior em uma variável chamada 'adaptador'.
O próximo passo é obter a entrada do EditText
. Isso realmente requer um pouco de reflexão. Você pode adicionar um OnKeyListener()
ao seu EditText
. No entanto, esse ouvinte recebe apenas alguns eventos importantes . Por exemplo, se um usuário digitar 'wyw', o texto preditivo provavelmente recomendará 'eye'. Até que o usuário escolha 'wyw' ou 'eye', você OnKeyListener
não receberá um evento importante. Alguns podem preferir essa solução, mas achei frustrante. Eu queria todos os eventos principais, então tive a opção de filtrar ou não. A solução é a TextWatcher
. Basta criar e adicionar TextWatcher
a ao EditText
e passar a ListAdapter
Filter
solicitação de filtro sempre que o texto for alterado. Lembre-se de remover o TextWatcher
in OnDestroy()
! Aqui está a solução final:
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);
}