AndroidでListViewを動的に更新する方法[終了]


159

Androidでは、ListViewユーザーの入力に基づいてフィルター処理を行うにはどうすればよいTextViewですか。表示されるアイテムは、値に基づいて動的に更新されます。

私はこのようなものを探しています:

-------------------------
| Text View             |
-------------------------
| List item             |
| List item             |
| List item             |
| List item             |
|                       |
|                       |
|                       |
|                       |
-------------------------

7
再開を指名します。私はこれを質問のより多くにするためにテキストを更新しました、そしてそれは答えがまだ入っているので明らかに貴重なコミュニティのリソースです
Hamy

質問をもう一度開いてください。それは明らかに役に立ちます。
SilentNot '19年

回答:


286

まず、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の上にEditTextが表示されます。次に、通常どおりにListActivityを作成しますがsetContentView()onCreate()メソッドに呼び出しを追加して、最近宣言したレイアウトを使用します。でListView特別にIDを付けたことを忘れないでください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と、前のが表示され、上に素敵なボックスが表示されます。そのボックスに何かをさせるには、ボックスから入力を受け取り、その入力をリストにフィルターする必要があります。多くの人がこれを手動で実行しようとしましたが、ほとんどの ListView Adapterクラスには、Filter自動的にフィルタリングを実行するために使用できるオブジェクトが付属しています。私達はちょうどからパイプへの入力が必要EditTextFilter。結構簡単です。簡単なテストを実行するには、この行をonCreate()呼び出しに追加します

adapter.getFilter().filter(s);

ListAdapterこれを機能させるには、変数を変数に保存する必要があることに注意してくださいArrayAdapter<String>。以前の変数を「アダプター」という変数に保存しました。

次のステップは、から入力を取得することEditTextです。これは実際には少し考えが必要です。をに追加できOnKeyListener()ますEditText。ただし、このリスナーは一部のキーイベントのみを受け取ります。たとえば、ユーザーが「wyw」と入力した場合、予測テキストは「目」を推奨する可能性があります。ユーザーが「wyw」または「eye」を選択するまで、OnKeyListenerキーイベントは受信されません。一部の人はこのソリューションを好むかもしれませんが、私はそれが苛立たしいと思いました。すべての重要なイベントが必要だったので、フィルタリングするかしないかを選択できました。解決策はTextWatcherです。単純に作成して追加TextWatcherするEditTextと、パスListAdapter Filterテキストを変更するたびに、フィルタ要求を。を削除することTextWatcherを忘れないでくださいOnDestroy()!これが最終的な解決策です:

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);
}

7
このソリューションのように、「次で始まる」ではなく「次を含む」でListViewをフィルタリングする簡単な方法はありますか?
ViktorBrešan

12
Viktor-興味のある単語がスペースで区切られている場合、これは自動的に行われます。そうでなければ、そうではありません。おそらく最も簡単な方法は、アダプタを拡張してサブクラス化し、getFilterメソッドをオーバーライドして、定義したFilterオブジェクトを返すことです。デフォルトのArrayFilterがどのように機能するかを理解するには、github.com / android / platform_frameworks_base / blob / master / core /…を参照してください。このコードの95%をコピーして479行目と486行目を変更するのは簡単です
Hamy

2
ハミー、素晴らしい記事!しかし、質問があります。これを実装し、入力する各文字の後に、ListViewが数秒間消えてから、戻ってフィルタリングされます。これを経験しましたか?私の直感は、リストに600以上の項目があり、重要なtoString()関数があるためです。
lowellk '23

2
小さい画面の横長モードでは、EditText +キーボードは画面全体を占め、ListViewは表示されません。解決策はありますか?
Martin Konicek、2011

4
これは本当に必要ですか?> OnDestroy()でTextWatcherを削除することを忘れないでください
Jojo

10

プログラムを実行すると強制終了します。

私は行を交換しました:

android:id = "@ + building_list / search_box"

android:id = "@ + id / search_box"

それが問題でしょうか?「@ + building_list」とは何ですか?


Johe、R.id.somethingと言うと、android:id = "@ + id / search_box"と言ったため、idに何かが存在します。android:id = "@ + building_list / search_box"と言った場合、コードでfindViewById(R.building_list.search_box);を呼び出すことができます。あなたが受けているトップレベルの例外は何ですか?このコードはテストコンパイルなしでコピーされるため、少なくとも1つのエラーがどこかに残っている可能性があります
Hamy

こんにちはハミー、「filterText =(EditText)findViewById(R.id.search_box);」を使用してコードで「@ + building_list / search_box」を参照しました だから不思議に思っていました。
j7nn7k 2010

1
入力を開始すると、forcecloseが発生します。エラーの一部:ERROR / AndroidRuntime(188):java.lang.NullPointerException 02-11 07:30:29.828:ERROR / AndroidRuntime(188):at xxx.com.ListFilter $ 1。 onTextChanged(ListFilter.java:46)02-11 07:30:29.828:ERROR / AndroidRuntime(188):at android.widget.TextView.sendOnTextChanged(TextView.java:6102)02-11 07:30:29.828:ERROR / AndroidRuntime(188):at android.widget.TextView.handleTextChanged(TextView.java:6143)02-11 07:30:29.828:ERROR / AndroidRuntime(188):at android.widget.TextView $ ChangeWatcher.onTextChanged(TextView.java :6286)
j7nn7k 2010

Joheさん 先端をありがとう!@ + idに変更するだけで修正できます
Hamy

4

フィルタリングに問題があり、その結果はフィルタリングされましたが、復元されませんでした

フィルタリング(アクティビティ開始)する前に、リストバックアップを作成しました(同じデータを含む別のリストのみ)。

フィルタリングでは、フィルターとリストアダプターはプライマリリストに接続されます。

ただし、フィルタ自体はバックアップリストのデータを使用しました。

これは私の場合、リストがすぐに更新され、search-term-charactersを削除した場合でも、すべての場合にリストが正常に復元されることを保証しました:)

とにかくこのソリューションに感謝します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.