How to search a list of Objects that are displayed

2019-06-12 03:19发布

I am currently trying to implement a SearchView, but the displayed search results change only for the first Search, everything else I enter into SearchView is ignored.

Here is my Code for Searching in my MainActivity.java:

testList = Arrays.asList(new TestItem("aw"), new TestItem("aa"), new TestItem("w"));

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.test_menu, menu);

    SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
    searchView.setOnQueryTextListener(this);
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onQueryTextChange(String newText) {
    List<TestItem> result = new ArrayList<>();
    for(TestItem t: testList) {
        if(t.getName().contains(newText) {
            result.add(t);
        }
    }
    adapter.changeList(result);
    return true;
}

adapter.changeList:

public void changeList(List<TestItem> newList) {
    this.list = new ArrayList<>(newList);
}

onQueryTextChange gets called after each text change, but the search result is shown only once. When entering a and Enter the RecyclerView shows aw and aa (is it normal to have to press Enter for onQueryTextChange to start?), but when I then enter aa the displayed items stay the same.

1条回答
霸刀☆藐视天下
2楼-- · 2019-06-12 04:03

I think your implementation is not correct. You don't need to press the enter for search result. For implementation you can keep a intact copy of your array list.Then make another temporary list form that list when query text is changed. So when you are filtering, you are searching the actual list not the filtered list.

1.pass search keyword to the list adapter

public boolean onQueryTextChange(String newText) {

    adapter.getFilter().filter(newText);
    return true;
}

2. In adapter implement Filterable and override method

@Override
public Filter getFilter() {
    if (frameFilter == null) {
        frameFilter = new FrameFilter();
    }

    return frameFilter;
}

3. Filtering class can be something like this: 'categoryMain' is my intact list and 'categoryTemp' is my temporary list

private class FrameFilter extends Filter {

    @Override
    protected FilterResults performFiltering(CharSequence constraint) {

        FilterResults filterResults = new FilterResults();
        if (constraint != null && constraint.length() > 0) {
            ArrayList<Category> tempList = new ArrayList<>();

            // search content in friend list
            Log.i("key",constraint.toString());
            for (Category category : categoriesMain) {
                if (category.getCategory_name().toLowerCase().contains(constraint.toString().toLowerCase())) {
                    tempList.add(category);
                }
            }
            filterResults.count = tempList.size();
            filterResults.values = tempList;
        } else {

            filterResults.count = categoriesMain.size();
            filterResults.values = categoriesMain.clone();
        }
        return filterResults;
    }

    /**
     * Notify about filtered list to ui
     *
     * @param constraint text
     * @param results    filtered result
     */
    @SuppressWarnings("unchecked")
    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {

        categoriesTemp = (ArrayList<Category>) results.values;
        notifyDataSetChanged();
    }
}
查看更多
登录 后发表回答