Androidでは、表示されるアイテムがListView
値に基づいて動的に更新されるユーザー入力に基づいてフィルタリングするTextView
をどのように使用できますか?
私はこのようなものを探しています:
-------------------------
| Text View |
-------------------------
| List item |
| List item |
| List item |
| List item |
| |
| |
| |
| |
-------------------------
最初に、EditTextとListViewの両方を持つXMLレイアウトを作成する必要があります。
<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>
これにより、ListViewの上にNice EditTextが表示され、すべてが適切にレイアウトされます。次に、通常どおりListActivityを作成しますが、setContentView()
メソッドにonCreate()
呼び出しを追加して、最近宣言したレイアウトを使用します。 ListView
をAndroid:id="@Android:id/list"
で特別に識別したことに注意してください。これにより、ListActivity
は、宣言されたレイアウトで使用するListView
を知ることができます。
@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());
}
ここでアプリを実行すると、前のListView
が表示され、上にNiceボックスが表示されます。そのボックスに何かをさせるには、そのボックスから入力を取得し、その入力にリストをフィルターさせる必要があります。多くの人がこれを手動で実行しようとしましたが、mostListView
Adapter
クラスには、フィルタリングを自動的に実行するために使用できるFilter
オブジェクトが付属しています。入力をEditText
からFilter
にパイプするだけです。それは非常に簡単です。クイックテストを実行するには、この行をonCreate()
呼び出しに追加します
adapter.getFilter().filter(s);
この作業を行うには、ListAdapter
を変数に保存する必要があることに注意してください。以前のArrayAdapter<String>
を 'adapter'という変数に保存しました。
次のステップは、EditText
から入力を取得することです。これには実際に少し考えが必要です。 EditText
にOnKeyListener()
を追加できます。ただし、このリスナーは一部のキーイベントのみを受け取ります。たとえば、ユーザーが「wyw」と入力すると、予測テキストは「eye」を推奨します。ユーザーが「wyw」または「eye」を選択するまで、OnKeyListener
はキーイベントを受け取りません。このソリューションを好む人もいるかもしれませんが、イライラすることがわかりました。すべての重要なイベントが欲しかったので、フィルタリングするかしないかの選択がありました。解決策はTextWatcher
です。 TextWatcher
を作成してEditText
に追加し、テキストが変更されるたびにListAdapter
Filter
にフィルターリクエストを渡すだけです。 OnDestroy()
のTextWatcher
を忘れずに削除してください!最終的な解決策は次のとおりです。
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);
}
プログラムを実行すると、強制終了します。
私は行を交換しました:
Android:id = "@ + building_list/search_box"
と
Android:id = "@ + id/search_box"
それが問題なのでしょうか? 「@ + building_list」とは何ですか?
私はフィルタリングに問題があり、その結果はフィルタリングされましたが、復元されません!
フィルタリング(アクティビティ開始)の前にリストバックアップを作成しました。(同じデータを含む別のリストのみ)
フィルター処理では、フィルターとリストアダプターはプライマリリストに接続されます。
ただし、フィルター自体はバックアップリストのデータを使用しました。
これにより、リストがすぐに更新され、search-term-charactersを削除しても、リストはすべてのケースで正常に復元されます。
とにかくこのソリューションをありがとう。