как фильтровать элементы списка при использовании базового адаптера в Android?

Я много искал о поиске элементов в представлении списка с помощью редактирования текста, и хотя я нашел много вопросов, похожих на мою проблему, но везде используется либо адаптер курсора, где отфильтрованный результат извлекается непосредственно из базы данных, либо используется некоторый список массивов.

В моем случае я использовал пару массивов для передачи текста для моего представления списка с помощью базового адаптера. Поскольку я никогда раньше не делал ничего подобного, я не могу понять, как использовать text watcher.

Я отладил код и обнаружил, что этот метод публикации результатов не вызывается, возможно, поэтому представление списка не может получить новые значения. Нужно ли мне снова вызывать класс listviewadaptercontacts с обновленными значениями в массиве имен внутри метода изменения текста.

Пожалуйста помоги.

public class AllContactsActivity extends ListActivity implements
android.view.View.OnClickListener, OnItemClickListener {

    ListView lv;
    ListViewAdapterContacts lva;
    String[] names, phones, ids, types;


    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        LayoutParams params = new RelativeLayout.LayoutParams(
            LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        LinearLayout mainLayout = new LinearLayout(this);
        mainLayout.setOrientation(LinearLayout.VERTICAL);
        LayoutInflater layoutInflater = getLayoutInflater();
        mainLayout.addView(layoutInflater.inflate(R.layout.allcontacts, null));
        mainLayout.addView(layoutInflater.inflate(R.layout.allbuttons, null));
        this.addContentView(mainLayout, params);

        configureBottomMenu();
        getContacts();

        lv = new ListView(getApplicationContext());
        lv = (ListView) findViewById(android.R.id.list);
        lva = new ListViewAdapterContacts(this, names, types, phones, ids); //passing arrays to class
        lv.setAdapter(lva);
        et = (EditText) findViewById(R.id.searchcontact);
        et.addTextChangedListener(new TextWatcher() {

            public void onTextChanged(CharSequence s, int start, int before, int count) { // TODO Auto-generated method stub
                lva.getFilter().filter(s);

                lva.notifyDataSetInvalidated();
                lva.notifyDataSetChanged();
                lv.setAdapter(lva);
            }

            public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {

                // TODO Auto-generated method stub

            }

            public void afterTextChanged(Editable s) {
                // TODO Auto-generated   method stub
            }
        });

        //some code
    }
}

public class ListViewAdapterContacts extends BaseAdapter implements Filterable {

    private ArrayFilter mFilter;
    private ArrayList < String > mOriginalValues;
    private final Object mLock = new Object();
    private List < String > mObjects;
    List list;

    Activity context;
    String[] names;
    String[] types;
    String[] numbers;
    String[] ids;
    public ListViewAdapterContacts(Activity context, String[] names, String[] types, String[] numbers, String[] ids) {
        // TODO Auto-generated constructor stub

        this.context = context;
        this.names = names;
        this.types = types;
        this.numbers = numbers;
        this.ids = ids;
        Object[] array = names;
        list = Arrays.asList(array);
    }



    public int getCount() {
        // TODO Auto-generated method stub 
        if (names == null) {
            return 0;
        } else {
            return names.length;
        }
    }

    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return null;
    }

    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return 0;
    }

    public class viewHolder {
        TextView top;
        TextView bottom;
        TextView downside;
        TextView base;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        viewHolder holder;
        if (convertView == null) {

            LayoutInflater inflator = context.getLayoutInflater();
            convertView = inflator.inflate(R.layout.textviewonly, null);

            holder = new viewHolder();
            holder.top = (TextView) convertView.findViewById(R.id.toptext);
            holder.bottom = (TextView) convertView.findViewById(R.id.bottomtext);
            holder.downside = (TextView) convertView.findViewById(R.id.lowest);
            holder.base = (TextView) convertView.findViewById(R.id.baseid);
            convertView.setTag(holder);
        } else {
            holder = (viewHolder) convertView.getTag();
        }
        holder.top.setText(names[position]);
        holder.bottom.setText(types[position]);
        holder.downside.setText(numbers[position]);
        holder.base.setText(ids[position]);
        return convertView;
    }

    public Filter getFilter() {
        // TODO Auto-generated method stub
        if (mFilter == null) {
            mFilter = new ArrayFilter();
        }
        return mFilter;
    }

    private class ArrayFilter extends Filter {

        @Override
        protected FilterResults performFiltering(CharSequence prefix) {
            FilterResults results = new FilterResults();

            if (mOriginalValues == null) {
                synchronized(mLock) {
                    //mOriginalValues = new ArrayList<String>(mObjects);

                    mOriginalValues = new ArrayList < String > (list);
                }
            }

            if (prefix == null || prefix.length() == 0) {
                synchronized(mLock) {
                    ArrayList < String > list = new ArrayList < String > (mOriginalValues);
                    results.values = list;
                    results.count = list.size();
                }
            } else {
                String prefixString = prefix.toString().toLowerCase();

                final ArrayList < String > values = mOriginalValues;
                final int count = values.size();

                final ArrayList < String > newValues = new ArrayList < String > (count);

                for (int i = 0; i < count; i++) {
                    final String value = values.get(i);
                    final String valueText = value.toString().toLowerCase();

                    // First match against the whole, non-splitted value
                    if (valueText.startsWith(prefixString)) {
                        newValues.add(value);
                    } else {
                        final String[] words = valueText.split(" ");
                        final int wordCount = words.length;

                        for (int k = 0; k < wordCount; k++) {
                            if (words[k].startsWith(prefixString)) {
                                newValues.add(value);
                                break;
                            }
                        }
                    }
                }

                results.values = newValues;
                results.count = newValues.size();
            }

            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            //noinspection unchecked
            mObjects = (List < String > ) results.values;
            if (results.count > 0) {
                notifyDataSetChanged();
            } else {
                notifyDataSetInvalidated();
            }
        }
    }
}

person prof_jack    schedule 05.12.2011    source источник
comment
почему бы не создать один контракт класса сущности и использовать List‹Contract› вместо использования String[] имен, телефонов, идентификаторов, типов, которые намного проще фильтровать данные.   -  person Michael Wang    schedule 05.12.2011
comment
но точка по-прежнему остается прежней. как выполнять фильтрацию, даже если я использую класс сущности   -  person prof_jack    schedule 05.12.2011
comment
Повторите List‹Contract›, чтобы проверить, соответствует ли какой-либо контракт какому-либо условию, такому как contract.name.equals(NAME), и поместите квалифицированный контракт в один новый список, а затем установите новый список в конструктор адаптера.   -  person Michael Wang    schedule 05.12.2011
comment
это означает, что я должен перебирать каждый элемент в списке. Что, если у меня есть 200 контактов, я думаю, что в этом случае для каждого символа, указанного в тексте редактирования, метод фильтра будет искать эту строку/символ в моем списке контактов. Ты думаешь, что это детройтское выступление.   -  person prof_jack    schedule 05.12.2011
comment
Если есть 200 контактов, я не думаю, что это влияет на производительность, в любом случае, вы можете попробовать.   -  person Michael Wang    schedule 05.12.2011
comment
stackoverflow.com/questions/10764675/.   -  person Anthony Flores    schedule 20.04.2014


Ответы (1)


В этом коде:

et.addTextChangedListener(new TextWatcher() {

    public void onTextChanged(CharSequence s, int start, int before, int count) { // TODO Auto-generated method stub
        lva.getFilter().filter(s);

        lva.notifyDataSetInvalidated();
        lva.notifyDataSetChanged();
        lv.setAdapter(lva);
    }

    public void beforeTextChanged(CharSequence s, int start, int count,
        int after) { 

      // TODO Auto-generated method stub

    }

    public void afterTextChanged(Editable s) {

        // TODO Auto-generated  method stub      
    }
});

В методе ontextChanged() используйте только:

lva.getFilter().filter(s);
person Mohit Verma    schedule 26.04.2012