Innanzitutto, è necessario creare un layout XML che abbia sia EditText sia 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>
Questo sistemerà tutto correttamente, con un bel EditText sopra ListView. Successivamente, crea un ListActivity come faresti normalmente, ma aggiungi una setContentView()
chiamata nel onCreate()
metodo in modo da utilizzare il nostro layout dichiarato di recente. Ricorda che abbiamo identificato il ListView
appositamente, con android:id="@android:id/list"
. Ciò consente ListActivity
di sapere quale ListView
vogliamo utilizzare nel nostro layout dichiarato.
@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'esecuzione dell'app ora dovrebbe mostrare il tuo precedente ListView
, con una bella casella sopra. Per fare in modo che quel riquadro faccia qualcosa, dobbiamo prendere l'input da esso e fare in modo che quell'input filtri l'elenco. Mentre molte persone hanno provato a farlo manualmente, la maggior parte delle ListView
Adapter
classi include un Filter
oggetto che può essere utilizzato per eseguire il filtraggio automagicamente. Dobbiamo solo reindirizzare l'input da EditText
in a Filter
. Si scopre che è abbastanza facile. Per eseguire un test rapido, aggiungi questa linea alla onCreate()
chiamata
adapter.getFilter().filter(s);
Si noti che sarà necessario salvare il tuo ListAdapter
in una variabile per far funzionare questo - ho salvato il mio ArrayAdapter<String>
da prima in una variabile chiamata 'adattatore'.
Il prossimo passo è ottenere l'input dal EditText
. Questo in realtà richiede un po 'di pensiero. Potresti aggiungere un OnKeyListener()
al tuo EditText
. Tuttavia, questo listener riceve solo alcuni eventi chiave . Ad esempio, se un utente inserisce "wyw", il testo predittivo probabilmente consiglierà "occhio". Fino a quando l'utente non sceglie "wyw" o "eye", OnKeyListener
non riceverai un evento chiave. Alcuni potrebbero preferire questa soluzione, ma l'ho trovata frustrante. Volevo ogni evento chiave, quindi ho potuto scegliere di filtrare o non filtrare. La soluzione è a TextWatcher
. Basta creare e aggiungere un TextWatcher
al EditText
e passare la ListAdapter
Filter
richiesta di un filtro ogni volta che il testo cambia. Ricorda di rimuovere TextWatcher
in OnDestroy()
! Ecco la soluzione 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);
}