ListView过滤器可视化问题

时间:2014-04-02 15:40:56

标签: android listview adapter android-arrayadapter

ArrayAdapter<T>子类上使用自定义过滤器时,在显示之前,我总是最终让容器ListView 在运行时显示所有元素,只需几分之一秒实际过滤的清单。

当用户使用SearchView / TextView进行过滤时,这尤其会损害用户体验,并且需要调用过滤器事件onQueryTextChange,这样过滤器似乎会在每次按键时重置

我的实现通常是这样的:

public class FilterAdapter extends ArrayAdapter<ListElement> {
    private Context mContext;
    public List<ListElement> listElements;

...

@Override
public Filter getFilter(){
    return new Filter(){
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {

            Locale currentLocale = mContext.getResources().getConfiguration().locale;
            constraint = constraint.toString().toLowerCase(currentLocale);

            FilterResults results = new FilterResults();

            if (constraint == null || constraint.length() == 0) {
                //get a COPY of the original elements array not to change it by reference
                results.values = new ArrayList<ListElement>(FilterAdapter.this.listElements);
                results.count = listElements.size();
            }
            else{
                List<ListElement> found = new ArrayList<ListElement>();
                for(ListElement item : FilterAdapter.this.listElements){
                    if(item.filterString().toLowerCase(currentLocale).contains(constraint)){
                        found.add(item);    //no need to create a copy of single element
                    }
                }
                results.values = found;
                results.count = found.size();
            }
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            clear();
            for (ListElement item : (List<ListElement>) results.values) {
                add(item);
            }
            notifyDataSetChanged();
        }
    };
}

根据我的理解,Filter.performFiltering子类AsyncTask(或者至少在自己的线程中运行,从未真正去过AOSP进行检查),Filter.publishResults只是UI的处理程序适配器的线程。

我看到过滤器的每个实现都倾向于在publishResults的开头和结尾调用ArrayList.clear()ArrayList.notifyDataSetChanged,并且我没有过滤器在没有明确的+通知的情况下工作...,尽管我和#39 ;很漂亮

是否有任何提示可以删除第二次重置的那一部分,并且只需一次从一个过滤列表转到另一个?

2 个答案:

答案 0 :(得分:0)

尝试将此android:scrollingCache="false"添加到布局文件中的<ListView>元素中。

答案 1 :(得分:0)

我实际上在询问了5m之后偶然发现了一个解决方案,同时解决了一个糟糕的getCount()问题:问题是同步,因为最初被怀疑。我这样称呼过滤器......

auxAdapter.getFilter().filter(currentUserTextFilter);

//and sequentially I replaced the old adapter on the list
contactsAdapter = auxAdapter;
listViewContacts.setAdapter(contactsAdapter);

//...bunch of other operations in between, and then...
Log.i(activityName, "Item count: " + listViewContacts.getAdapter().getCount());

...并且.filter(String constraint)没有阻止并且实际上花费的时间比设置新适配器要长,所以它显示了一个完整的列表,并且还让我意外(但正确)项目计数(当我实际调试那个计数时)。

工作代码使用filter(CharSequence constraint, Filter.FilterListener listener)而不是仅限制约的版本:

auxAdapter.getFilter().filter(currentUserTextFilter, new Filter.FilterListener() {
            public void onFilterComplete(int count) {
                contactsAdapter = auxAdapter;

                contactsAdapter.setNotifyOnChange(true);
                listViewContacts.setAdapter(contactsAdapter);
                updateTitle();
            }
        });