Android Action Bar Search: How to filter a list by the property of a list item?

12,890

the most efficient way is to implement a filter on your adapter. For this you must implement the interface Filterable (implements Filterable). Then implement the method getFilter like this.

@Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {
                List<Object> filteredResult = getFilteredResults(charSequence);

                FilterResults results = new FilterResults();
                results.values = filteredResult;
                results.count = filteredResult.size();

                return results;
            }

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
                listaFiltrada = (ArrayList<Documento>) filterResults.values;
                MyAdapter.this.notifyDataSetChanged();
            }


            private ArrayList<Object> getFilteredResults(CharSequence constraint){
                if (constraint.length() == 0){
                    return  listaDocumentos;
                }
                ArrayList<Object> listResult = new ArrayList<Object>();
                for (Object obj : listaTotal){
                    if (condition){
                        listResult.add(obj);
                    }
                }
                return listResult;
            }
        };
    }

Finally, in your Fragment or Activity, in the method onCreateOptionsMenu get the EditText (search) and add this:

final EditText editText = (EditText) menu.findItem(R.id.menu_buscar).getActionView();
        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
                if (myAdapter != null) {
                    myAdapter.getFilter().filter(charSequence);
                }
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        });

Hope it helps you :)

Share:
12,890
Ishara Amarasekera
Author by

Ishara Amarasekera

Native and cross platform mobile application developer.

Updated on June 04, 2022

Comments

  • Ishara Amarasekera
    Ishara Amarasekera almost 2 years

    I have a list view with a list item, which has few text views and a checkbox. Using action bar search, I need to filter out the list by a text view value.

    This is my list which I need to filter by "Priority".

    enter image description here

    This is the method I used to filter the list from the data adopter.

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main, menu);
    
         SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
            SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
    
                searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
                searchView.setIconifiedByDefault(false);   
    
            SearchView.OnQueryTextListener textChangeListener = new SearchView.OnQueryTextListener() 
            {
                @Override
                public boolean onQueryTextChange(String newText) 
                {
                    // this is your adapter that will be filtered
                    dataAdapter.getFilter().filter(newText);
                    System.out.println("on text chnge text: "+newText);
                    return true;
                }
                @Override
                public boolean onQueryTextSubmit(String query) 
                {
                    // this is your adapter that will be filtered
                    dataAdapter.getFilter().filter(query);
                    System.out.println("on query submit: "+query);
                    return true;
                }
            };
            searchView.setOnQueryTextListener(textChangeListener);
    
            return super.onCreateOptionsMenu(menu);
    
    }
    

    I have set the dataAdopter to my listview which contains few elements, i.e 3 text views and a check box.

    // create an ArrayAdaptar from the String Array
        dataAdapter = new MyCustomAdapter(this, R.layout.task_info, taskList);
        listView = (ListView) findViewById(R.id.listView1);
    // Assign adapter to ListView
        listView.setAdapter(dataAdapter);
    

    But when I set the adapter in the following way; using just a string array of values, the filtering happens without any issues

    String[] dataArray = new String[] {"High","Medium", "Low", "Medium", "High", "Low","High"};
    listView = (ListView) findViewById(R.id.listview);
    myAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,  dataArray);
    listView.setAdapter(myAdapter);
    

    Is there any method that I can use to filter the list by the value of a text view inside a list item? Or is there any alternative method to implement the desired functionality.

  • Ishara Amarasekera
    Ishara Amarasekera almost 10 years
    Thanks for your idea @Alejandro. I decided to use an Edit Text with a search instead of Action Bar search. I followed your instructions. But my implementation in the adopter was slightly different to what you posted.