多项选择可搜索列表视图 [英] Multiple Choice Searchable ListView

查看:12
本文介绍了多项选择可搜索列表视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,我有一个可以正常工作的多选 ListView.我选中了联系人的框(保存在 String[] 中)并且可以正常返回值.因为有些人有一堆联系人,所以我想创建一个类似于 Android 电话簿的搜索栏.我创建了一个 EditText 并将其对齐在我的列表上方.我在 StackOverflow 上找到了过滤代码,效果很好.

OK I have a multiple choice ListView that works fine. I check the boxes for the contacts (held in a String[]) and can return the values fine. Because some people have a bunch of contacts I wanted to create a search bar kind of like the stock one for the Android phone book. I created an EditText and aligned it above my list. I found the filtering code here on StackOverflow and it works wonderfully.

我的问题:

当您过滤某人的姓名并选择姓名时,当您从 EditText 退格或继续键入时,您选择的姓名的正确位置不会保存.例如,如果我开始输入Adam"并进入Ada"并选择它,如果我退格输入Carol",则选择Ada"所在的任何位置.它从点击中收集亚当"所在的位置(假设为 2),当列表恢复时,即使亚当不再存在,也会检查该位置 (2).我需要一种方法来收集名称.. 然后当列表恢复或再次搜索时,检查名称 Adam 而不是 POSITION Adam 之前所在的位置.除了创建大量数组之外,我绝对没有任何想法并且可以真正使用一些帮助.以下是我正在使用的一些代码:

When you filter someones name out, and you select the name, when you either backspace from the EditText or continue typing, the correct position of the name you selected is not saved. For example, if I start typing "Adam" and get to "Ada" and select it, if I backspace to type in "Carol", whatever position "Ada" was at is selected. It gathers the place that "Adam" was at from the click (Let's say 2) and when the list is restored checks that position (2) even though Adam is not there anymore. I need a way to gather the name.. then when the list is restored or searched again, the NAME Adam is checked and not the POSITION Adam was previously at. I have absolutely no ideas other than creating tons of Arrays and could really use some help. Below is some of the code I'm using:

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

        }

    };

推荐答案

我最终没有找到比我将在下面列出的方法更好的方法.这段代码我已经不多用了,如果有更好的解决方案,希望有人贴在某个地方.

I never ended up finding a better method than the one I am going to list below. I do not use this code much anymore, and if there is a better solution, I hope someone has it posted somewhere.

我最终做的是创建一个 ArrayList 来保存选定的名称.如果选中名称,则将该名称推入ArrayList,如果未选中,则从列表中弹出.When afterTextChanged is selected, the list is iterated through and the names are checked if they are currently listed in the adapter.当您完成选择过程并想继续时,我清除 EditText 以清除过滤器,因此在 ListView 中填充完整列表并将所有联系人设置为选中(如果它们存在于 ArrayList 中).

What I ended up doing was creating an ArrayList to hold the selected names. If the name is selected, the name is pushed into the ArrayList, and if it is unchecked, it is popped from the list. When afterTextChanged is selected, the list is iterated through and the names are checked if they are currently listed in the adapter. When you finish with the selection process and want to continue, I clear the EditText to clear the filter, therefore populating the complete list in the ListView and setting all of the contacts to selected if they exist in the ArrayList.

请注意,我对仅列出姓名的联系人列表使用了自定义适配器,因此如果您使用其他类型的数据,此解决方案可能会变得更加混乱,我将此方法视为一种黑客解决方案:

Note, I use a custom adapter for a list of contacts that only list names, so this solution may get more confusing if you use other types of data, and I look at this method as a hacked solution:

/** 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 中的某些内容,而当您更改过滤.

You don't want to use Indexes when using the filters because index 1 might be something in one ListView, and it might be another ListView item when you change the filter.

这篇关于多项选择可搜索列表视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆