【问题标题】:ListView filter visual issueListView 过滤器视觉问题
【发布时间】:2014-04-02 15:40:56
【问题描述】:

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.performFilteringAsyncTask 的子类(或者至少在自己的线程中运行,从未真正去 AOSP 进行检查),而 Filter.publishResults 只是适配器 UI 线程的处理程序。

我见过的每个过滤器实现都倾向于在 publishResults 的开头和结尾调用 ArrayList.clear()ArrayList.notifyDataSetChanged,而且我从来没有让过滤器在没有 clear+notify 的情况下工作......虽然我很漂亮

有什么技巧可以消除第二次重置的那一小部分,然后一次性从一个过滤列表转到另一个过滤列表?

【问题讨论】:

    标签: android listview adapter android-arrayadapter


    【解决方案1】:

    尝试将此android:scrollingCache="false" 添加到布局文件中的&lt;ListView&gt; 元素中。

    【讨论】:

      【解决方案2】:

      实际上,我在询问 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();
                  }
              });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-02-08
        • 2014-01-23
        • 1970-01-01
        • 2012-07-28
        • 2011-07-29
        • 2021-12-28
        • 1970-01-01
        相关资源
        最近更新 更多