Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ListView Filter filters correctly but shows wrong result

I have a custom Adapter that I use to display custom objects in a ListView. Furthermore, I used a SearchView that allows me search through the ListView and filter out results. However, I have noticed some strange behavior when I try to enter a search. As long as I search for an item that is on the list, an item will show up in the filter - however , items are always displayed from the top of the list. If there are 10 items in the list and a search produces 5 matches then the result will show the first 5 items in the list instead of the 5 actual matches. For example, consider this list with 6 motorcycle helmets on it:

  • Bell
  • Icon
  • Harley Davidson
  • Joe Rocket
  • Shoei
  • Thor

If I search for "ho", the resulting list should be as follows:

  • Shoei
  • Thor

However, the list that I get is the first two items:

  • Bell
  • Icon

I can't figure out why the search isn't working properly. Any help would be appreciated. My code is shown below...

HelmetActivity.java

public class HelmetActivity extends ActionBarActivity implements
        SearchView.OnQueryTextListener{

    private Menu menu;
    private ListView listView;
    private HelmetAdapter helmetAdapter;
    private List<Helmet> arrayList;
    private SearchManager searchManager;
    private SearchView searchView;
    private MenuItem searchMenuItem;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.helmet_activity);
        ActionBar actionBar = getSupportActionBar();
        actionBar.setElevation(0);
        listView = (ListView) findViewById(R.id.helmet_listview);
        listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        arrayList = new ArrayList<Helmet>();
        listView.setLongClickable(true);
        helmetAdapter = new HelmetAdapter(this, R.layout.helmet, arrayList);
        listView.setAdapter(helmetAdapter);

        arrayList.add(new Helmet("Bell"));
        arrayList.add(new Helmet("Icon"));
        arrayList.add(new Helmet("Harley Davidson"));
        arrayList.add(new Helmet("Joe Rocket"));
        arrayList.add(new Helmet("Shoei"));
        arrayList.add(new Helmet("Thor"));
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        this.menu = menu;
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.helmet_activity_menu, menu);
        SearchManager searchManager = (SearchManager) getSystemService(
                Context.SEARCH_SERVICE);
        searchMenuItem = menu.findItem(R.id.action_search);
        searchView = (SearchView) searchMenuItem.getActionView();
        searchView.setSearchableInfo(searchManager.getSearchableInfo(
                getComponentName()));
        searchView.setSubmitButtonEnabled(true);
        searchView.setOnQueryTextListener(HelmetActivity.this);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onQueryTextSubmit(String query) {
        return false;
    }

    @Override
    public boolean onQueryTextChange(String newText)
    {
        helmetAdapter.getFilter().filter(newText);

        return true;
    }
}

HelmetAdapter.java

public class HelmetAdapter extends ArrayAdapter<Helmet> implements Filterable
{
    private int resource;
    private LayoutInflater inflater;
    private Context context;
    private List<Helmet> helmetList;
    private List<Helmet> filteredHelmetList;
    private HelmetFilter helmetFilter;

    public HelmetAdapter (Context pContext, int pResource, List<Helmet> helmetList)
    {
        super (pContext, pResource, helmetList);
        resource = pResource;
        inflater = LayoutInflater.from (pContext);
        context = pContext;
        this.helmetList = helmetList;
        this.filteredHelmetList = helmetList;
        getFilter();
    }

    @Override
    public View getView (final int position, View convertView, ViewGroup parent)
    {

        if (convertView == null)
        { convertView = inflater.inflate(resource, parent, false); }

        String uri;
        int imageResource;
        Drawable image;
        Helmet helmet = getItem (position);
        TextView hName = (TextView) convertView.findViewById(R.id.h_name);
        hName.setText(helmet.getName());

        return convertView;
    }

    @Override
    public int getCount()
    { return filteredHelmetList.size(); }

    @Override
    public Filter getFilter()
    {
        if (helmetFilter == null)
        {
            helmetFilter = new HelmetFilter();
        }

        return helmetFilter;
    }

    private class HelmetFilter extends Filter
    {
        @Override
        protected FilterResults performFiltering (CharSequence constraint)
        {
            FilterResults filterResults = new FilterResults();
            if (constraint != null && constraint.length() > 0)
            {
                ArrayList<Helmet> temporaryHelmetList = new ArrayList<Helmet>();
                for (Helmet helmet : helmetList)
                {
                    if (helmet.getName().toLowerCase().contains(constraint.toString()
                            .toLowerCase()))
                    {
                        temporaryHelmetList.add(helmet);
                    }
                }
                filterResults.count = temporaryHelmetList.size();
                filterResults.values = temporaryHelmetList;
            }
            else
            {
                filterResults.count = helmetList.size();
                filterResults.values = helmetList;
            }
            return filterResults;
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results)
        {
            filteredHelmetList = (ArrayList<Helmet>) results.values;
            notifyDataSetChanged();
        }
    }
}

Helmet.java

public class Helmet
{

    public Helmet (String name)
    {
        super();
        this.name = name;
    }

    private String     name;

    public String getName ()
    {
        return name;
    }

    public void setName (String pName)
    {
        this.name = pName;
    }
}
like image 682
Willis Avatar asked Feb 01 '15 03:02

Willis


1 Answers

It looks to me like your problem most likely lies in the getView(..) method of your adapter.

This line in particular -

Helmet helmet = getItem (position);

If you are returning the item in your original array of helmets then that would explain why you're getting the results you are. However, I can't be sure because I don't see your getItem(..) method posted in your code. If this is indeed the case then of course you would want to be returning your filtered results here (if there are any) instead of those from the unfiltered list.

like image 188
bwegs Avatar answered Oct 28 '22 05:10

bwegs