Фильтрация ListView с помощью SearchView и пользовательского адаптера

#android #android-listview #filter #android-arrayadapter

#Android #android-listview #Фильтр #android-arrayadapter

Вопрос:

Мне не удалось выполнить сортировку моего ListView. Когда я ввожу SearchView, ничего не происходит. В моем ListView нет изменений. Я безуспешно сравнивал примеры, найденные здесь и в других местах. Посредством отладки я подтвердил, что фильтр действительно работает, я вижу, что filteredArray заполняется теми данными, которые были отфильтрованы, но, опять же, никаких изменений в ListView.

Вот что у меня есть на данный момент. В MainActivity.class ..

 public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);

        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();

        searchView.setSubmitButtonEnabled(false);
        searchView.setQueryHint("Enter #..");
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));

        SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String s) {
                ListView listView = (ListView) findViewById(R.id.main_listView);
                listView.setTextFilterEnabled(true);

                if (s.isEmpty()) {
                    listView.clearTextFilter();
                } else {
                    customAdapter.getFilter().filter(s);
                }

                return true;
            }
        };

        searchView.setOnQueryTextListener(queryTextListener);

        return super.onCreateOptionsMenu(menu);
    }
  

Я создаю объект customAdapter, подобный этому, и listCustom содержит все классы CustomResults.

 customAdapter = new CustomAdapter(MainActivity.this, listCustom);
  

Пользовательский адаптер:

 public class CustomAdapter extends BaseAdapter implements Filterable {
    private static ArrayList<CustomResults> customArrayList;
    private static ArrayList<CustomResults> filteredArrayList;

    private LayoutInflater mInflater;

    public CustomAdapter(Context context, ArrayList<CustomResults> results) {
        customArrayList = results;
        mInflater = LayoutInflater.from(context);
    }

    public int getCount() {
        return customArrayList.size();
    }

    public Object getItem(int position) {
        return customArrayList.get(position);
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.custom_row, null);

            holder = new ViewHolder();
            holder.name = (TextView) convertView.findViewById(R.id.name);
            holder.num = (TextView) convertView.findViewById(R.id.number);


            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.name.setText(customArrayList.get(position).getName());
        holder.num.setText(customArrayList.get(position).getNum());

        return convertView;
    }

    static class ViewHolder {
        TextView name;
        TextView num;
    }

    @Override
    public Filter getFilter() {
        Filter filter = new Filter() {

            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {

                if (results.count == 0) {
                    notifyDataSetInvalidated();
                } else {
                    filteredArrayList = (ArrayList<CustomResults>) results.values;
                    notifyDataSetChanged();
                }

            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {

                String filterString = constraint.toString().toLowerCase();
                FilterResults results = new FilterResults();

                int count = customArrayList.size();

                ArrayList<CustomResults> filteredList = new ArrayList<CustomResults>();

                for (CustomResults custom : customArrayList) {
                    filteredList.add(custom);
                }

                String filterableString ;

                for (int i = 0; i < count; i  ) {
                    filterableString = customArrayList.get(i).getNum();
                    if (filterableString.toLowerCase().contains(filterString)) {
                        filteredList.add(customArrayList.get(i));
                    } else if (customArrayList.get(i).getName().toLowerCase().contains(filterString)) {
                        filteredList.add(customArrayList.get(i));
                    }
                }

                results.values = filteredList;
                results.count = filteredList.size();

                return results;
            }
        };

        return filter;

    }
  

Ответ №1:

getView () и другие функции всегда извлекаются из customArrayList и никогда из filteredArrayList.

Комментарии:

1. Не могли бы вы немного подробнее рассказать об этом? Я все еще новичок здесь. Как бы я справился с этим в publishResults и заставил listview обновляться на основе того, по чему я его фильтрую?

2. В конструкторе теперь вы присваиваете результаты только одному списку. Назначьте их обоим спискам. Пусть getView и другие функции извлекаются из отфильтрованного списка. И, наконец, в publishResults при results.count ==0 назначьте пользовательский список отфильтрованному списку, прежде чем уведомлять об изменении набора данных.

3. Спасибо, ваши ответы привели меня к обнаружению моей проблемы.