Пользовательский фильтр ArrayAdapter в ListView

Я начинаю в Android, но я попытался создать настраиваемую фильтрацию списка, и я работал как-то. Единственная проблема, с которой я столкнулся, заключается в том, что ArrayList, что я сохранил все значения («оригинальный» ArrayList), становится все ниже и ниже по элементам в каждой фильтрации. Я не могу это объяснить, но я подумал, что вы можете мне как-то помочь.

В любом случае, это Custom Custom ArrayAdaptor:

public class PkmnAdapter extends ArrayAdapter<Pkmn> { private ArrayList<Pkmn> original; private ArrayList<Pkmn> fitems; private Filter filter; public PkmnAdapter(Context context, int textViewResourceId, ArrayList<Pkmn> items) { super(context, textViewResourceId, items); this.original = items;//new ArrayList<Pkmn>(); this.fitems = items;//new ArrayList<Pkmn>(); } @Override public void add(Pkmn item){ original.add(item); } @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.row, null); } Pkmn pkmn = original.get(position); if (pkmn != null) { TextView tt = (TextView) v.findViewById(R.id.RlabPName); TextView dex = (TextView)v.findViewById(R.id.RlabDex); ImageView img = (ImageView)v.findViewById(R.id.RimgPkmn); if (tt != null) { tt.setText(pkmn.getName()); } if (dex != null){ dex.setText(CalcDex(pkmn.getId())); } if (img != null){ int resId = getContext().getResources().getIdentifier("dex" + pkmn.getId(), "drawable", "com.compileguy.pokebwteam"); img.setImageResource(resId); } } return v; } @Override public Filter getFilter() { if (filter == null) filter = new PkmnNameFilter(); return filter; } private class PkmnNameFilter extends Filter { @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); String prefix = constraint.toString().toLowerCase(); if (prefix == null || prefix.length() == 0) { ArrayList<Pkmn> list = new ArrayList<Pkmn>(original); results.values = list; results.count = list.size(); } else { final ArrayList<Pkmn> list = original; int count = list.size(); final ArrayList<Pkmn> nlist = new ArrayList<Pkmn>(count); for (int i=0; i<count; i++) { final Pkmn pkmn = list.get(i); final String value = pkmn.getName().toLowerCase(); if (value.startsWith(prefix)) { nlist.add(pkmn); } } results.values = nlist; results.count = nlist.size(); } return results; } @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint, FilterResults results) { fitems = (ArrayList<Pkmn>)results.values; clear(); int count = fitems.size(); for (int i=0; i<count; i++) { Pkmn pkmn = (Pkmn)fitems.get(i); add(pkmn); } if (fitems.size() > 0) notifyDataSetChanged(); else notifyDataSetInvalidated(); } } private String CalcDex(int id){ String s = String.valueOf(id); if (s.length() == 1) s = "00"+s; else if (s.length() == 2) s = "0"+s; return '#'+s; } 

}

ПРИМЕЧАНИЕ. В представлении list правильно отображаются элементы, но когда для exaple я удаляю букву в поле редактирования (которое запускает фильтрацию), здесь возникают проблемы.

— РЕДАКТИРОВАТЬ —

@Janusz: Большое спасибо за ваш ответ. Это решило мою проблему.

Вот исходный код, который работает для меня, поэтому, если у кого-то есть такая же проблема, они могут попробовать это:

 private ArrayList<Pkmn> original; private ArrayList<Pkmn> fitems; private Filter filter; public PkmnAdapter(Context context, int textViewResourceId, ArrayList<Pkmn> items) { super(context, textViewResourceId, items); this.original = new ArrayList<Pkmn>(items); this.fitems = new ArrayList<Pkmn>(items); } @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.row, null); } Pkmn pkmn = fitems.get(position); if (pkmn != null) { TextView tt = (TextView) v.findViewById(R.id.RlabPName); TextView dex = (TextView)v.findViewById(R.id.RlabDex); ImageView img = (ImageView)v.findViewById(R.id.RimgPkmn); if (tt != null) { tt.setText(pkmn.getName()); } if (dex != null){ dex.setText(CalcDex(pkmn.getId())); } if (img != null){ int resId = getContext().getResources().getIdentifier("dex" + pkmn.getId(), "drawable", "com.compileguy.pokebwteam"); img.setImageResource(resId); } } return v; } @Override public Filter getFilter() { if (filter == null) filter = new PkmnNameFilter(); return filter; } private class PkmnNameFilter extends Filter { @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); String prefix = constraint.toString().toLowerCase(); if (prefix == null || prefix.length() == 0) { ArrayList<Pkmn> list = new ArrayList<Pkmn>(original); results.values = list; results.count = list.size(); } else { final ArrayList<Pkmn> list = new ArrayList<Pkmn>(original); final ArrayList<Pkmn> nlist = new ArrayList<Pkmn>(); int count = list.size(); for (int i=0; i<count; i++) { final Pkmn pkmn = list.get(i); final String value = pkmn.getName().toLowerCase(); if (value.startsWith(prefix)) { nlist.add(pkmn); } } results.values = nlist; results.count = nlist.size(); } return results; } @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint, FilterResults results) { fitems = (ArrayList<Pkmn>)results.values; clear(); int count = fitems.size(); for (int i=0; i<count; i++) { Pkmn pkmn = (Pkmn)fitems.get(i); add(pkmn); } } } } 

Solutions Collecting From Web of "Пользовательский фильтр ArrayAdapter в ListView"

Ваша проблема заключается в следующих строках:

 this.original = items; this.fitems = items; 

Элементы – это список, который вы используете для своего ListView, и его размещение в двух разных переменных не выводит из него два разных списка. Вы указываете только два элемента списка.

Вы можете использовать:

 this.fitems = new ArrayList(items); 

Который должен генерировать новый список, и изменения в этом списке изменят только список фидов.

Вы можете добиться такого же эффекта, просто создав метод toString() в вашем классе Pkmn, который возвращает значение, которое вы хотите фильтровать.

Лучший способ найти фильтр ArrayAdapter – создать собственный класс фильтра:

 private class MyFilter extends Filter 

То в этой функции создайте новый массив объектов, который будет отображаться после фильтра (вы можете найти хорошую реализацию в исходном коде class ArrayAdapter )

 @Override protected FilterResults performFiltering(CharSequence prefix) 

Теперь трюк в этом методе

 @Override protected void publishResults(CharSequence constraint, FilterResults results) 

Когда вы используете адаптер Array, вы не можете это сделать:

 myAdapterData = results.values 

С тех пор вы отключите свои данные от суперданных, вы должны сделать это, чтобы сохранить ссылку на супер исходный массив данных:

 data.clear(); data.addAll((List<YourType>) results.values); 

И затем переопределить

getFilter ()

В вашем адаптере, например:

 @Override public Filter getFilter() { if (filter == null) { filter = new MyFilter(); } return filter; }