【问题标题】:ListView Filter filters correctly but shows wrong resultListView Filter 过滤正确但显示错误结果
【发布时间】:2015-02-01 03:59:44
【问题描述】:

我有一个自定义的Adapter,用于在ListView 中显示自定义对象。此外,我使用了SearchView,它允许我搜索ListView 并过滤掉结果。但是,当我尝试输入搜索时,我注意到了一些奇怪的行为。只要我搜索列表中的项目,过滤器中就会显示一个项目 - 但是,项目总是从列表顶部显示。如果列表中有 10 个项目并且搜索产生 5 个匹配项,则结果将显示列表中的前 5 个项目,而不是 5 个实际匹配项。例如,考虑这个列表,上面有 6 个摩托车头盔:

  • 贝尔
  • 图标
  • 哈雷戴维森
  • 乔火箭
  • 松英
  • 雷神

如果我搜索“ho”,结果列表应该如下:

  • Shoei
  • Tr

但是,我得到的列表是前两项:

  • 钟声
  • 图标

我不知道为什么搜索不能正常工作。任何帮助,将不胜感激。我的代码如下所示...

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;
    }
}

【问题讨论】:

    标签: java android android-listview android-adapter searchview


    【解决方案1】:

    在我看来,您的问题很可能出在适配器的 getView(..) 方法上。

    尤其是这一行-

    Helmet helmet = getItem (position);
    

    如果您要退回原始头盔阵列中的物品,那么这就解释了为什么您会得到这样的结果。但是,我不能确定,因为我没有在您的代码中看到您的 getItem(..) 方法。如果确实如此,那么您当然希望在此处返回过滤结果(如果有的话),而不是未过滤列表中的结果。

    【讨论】:

    • 我最终修改了我的 getItemgetView 方法,现在它可以工作了。感谢您为我指明正确的方向。
    • @Willis 你做了什么??我和你有同样的问题!提前致谢!
    猜你喜欢
    • 1970-01-01
    • 2021-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-03
    • 2021-09-09
    • 2020-11-15
    相关资源
    最近更新 更多