12

OK、正常に動作する複数選択の ListView があります。連絡先 (String[] に保持されている) のボックスをチェックすると、値を正常に返すことができます。たくさんの連絡先を持っている人もいるので、Android の電話帳のストックのような検索バーを作りたいと思いました。EditText を作成し、リストの上に配置しました。StackOverflow でフィルタリング コードを見つけましたが、素晴らしく機能します。

私の問題:

誰かの名前をフィルターで除外して名前を選択すると、EditText からバックスペースするか入力を続けると、選択した名前の正しい位置が保存されません。たとえば、「Adam」と入力し始めて「Ada」を選択すると、バックスペースで「Carol」と入力すると、「Ada」があった位置が選択されます。クリックから「アダム」がいた場所を収集し(2としましょう)、リストが復元されると、アダムがもうそこにいなくてもその位置(2)をチェックします。名前を収集する方法が必要です。その後、リストが復元または再度検索されると、Adam が以前にいた位置ではなく、名前 Adam がチェックされます。大量の配列を作成する以外にまったくアイデアがなく、本当に助けが必要です。以下は、私が使用しているコードの一部です。

    @Override
      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.contacts_list);


        myListView = (ListView)findViewById(android.R.id.list);
        search_EditText = (EditText) findViewById(R.id.search_EditText);
        search_EditText.addTextChangedListener(filterTextWatcher);

        adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, ContactsList); 
        setListAdapter(adapter);

        myListView.setItemsCanFocus(false);
        getListView().setChoiceMode(2);
        myListView.setTextFilterEnabled(true);
        myListView.setFastScrollEnabled(true);
        myListView.invalidate();
}

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

        }

    };
4

2 に答える 2

11

以下にリストする方法よりも優れた方法を見つけることは決してありませんでした。私はこのコードをあまり使用しません。より良い解決策があれば、誰かがどこかに投稿してくれることを願っています。

私がやったことはArrayList、選択した名前を保持する を作成することでした。名前が選択されている場合は名前が にプッシュされ、ArrayListチェックされていない場合はリストからポップされます。を選択するafterTextChangedと、リストが繰り返され、名前が現在アダプタにリストされているかどうかがチェックされます。選択プロセスを終了して続行する場合はEditText、フィルターをクリアしてフィルターをクリアします。したがって、ListView に完全なリストが入力され、ArrayList に存在する場合はすべての連絡先が選択済みに設定されます。

名前のみをリストする連絡先のリストにはカスタム アダプターを使用しているため、他の種類のデータを使用すると、このソリューションはさらに混乱する可能性があることに注意してください。この方法は、ハッキングされたソリューションと見なされます。

/** Used for filter **/
private TextWatcher filterTextWatcher = new TextWatcher() {

    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        ListView listview = getListView();

        SparseBooleanArray checked = listview.getCheckedItemPositions();
        for (int i = 0; i < ContactsList.length; i++) {
            if (checked.get(i) == true) {
                Object o = getListAdapter().getItem(i);
                String name = o.toString();
                // if the arraylist does not contain the name, add it
                if (selected.contains(name)){ 
                    // Do Nothing
                } else {
                    selected.add(name);
                }
            }
        }           
    } //<-- End of beforeTextChanged

    public void onTextChanged(CharSequence s, int start, int before, int count) {           
        adapter.getFilter().filter(s);              
    } //<-- End of onTextChanged

    public void afterTextChanged(Editable s) {
        ListView listview = getListView();
        // Uncheck everything:
        for (int i = 0; i < listview.getCount(); i++){
            listview.setItemChecked(i, false);                  
        }

        adapter.getFilter().filter(s, new Filter.FilterListener() {
            public void onFilterComplete(int count) {
                adapter.notifyDataSetChanged();
                ListView listview = getListView();
                for (int i = 0; i < adapter.getCount(); i ++) {
                    // if the current (filtered) 
                    // listview you are viewing has the name included in the list,
                    // check the box
                    Object o = getListAdapter().getItem(i);
                    String name = o.toString();
                    if (selected.contains(name)) {
                        listview.setItemChecked(i, true);
                    } else {
                        listview.setItemChecked(i, false);
                    }
                }

            }
        });         
    } //<-- End of afterTextChanged

}; //<-- End of TextWatcher

フィルターを使用するときにインデックス 1 を使用する必要はありません。フィルターを変更するListViewと、インデックス 1 が別のListViewアイテムになる可能性があるからです。

于 2012-09-13T00:51:55.347 に答える