无法通过 ListView 搜索,返回零结果

Posted

技术标签:

【中文标题】无法通过 ListView 搜索,返回零结果【英文标题】:Cannot search through the ListView, returns zero results 【发布时间】:2019-09-20 21:15:51 【问题描述】:

我正在使用带有自定义适配器的 ListView,并且我有一个 EditText 用于搜索列表。 当我在 EditText 中键入任何内容时,它会用 ListView 清空。 注意:我在片段中的对话框中显示 ListView

我也添加了 TextChangedListener。 不知道我哪里出错了。 请提出建议。

CompanyAdapter companyAdapter;

private void showCompaniesDialog(List<Company> companies) 
        if(companies != null) 
            final Dialog dialog = new Dialog(getContext());
            // dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            dialog.setCancelable(false);
            dialog.setContentView(R.layout.dialog_company_listview);

            Button btndialog = (Button) dialog.findViewById(R.id.btndialog);
            btndialog.setOnClickListener(new View.OnClickListener() 
                @Override
                public void onClick(View v) 

                    dialog.dismiss();
                
            );

            ListView listView = (ListView) dialog.findViewById(R.id.listview);
            companyAdapter = new CompanyAdapter(getActivity(), 0, companies);
            listView.setAdapter(companyAdapter);

            //HERE I SET THE TEXT FILTER ENABLED
            listView.setTextFilterEnabled(true);

            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() 
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
                    //textView.setText("You have clicked : " + companies[position]);
                    dialog.dismiss();
                
            );

            //HERE I ADD CHANGED LISTENER
            EditText etSearch = (EditText) dialog.findViewById(R.id.etSearch);
            etSearch.addTextChangedListener(new TextWatcher() 
                @Override
                public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) 

                

                @Override
                public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) 
                    companyAdapter.getFilter().filter(charSequence);
                

                @Override
                public void afterTextChanged(Editable editable) 
                    //companyAdapter.getFilter().filter(editable);
                
            );

            dialog.show();
        

    

公司适配器

    public class CompanyAdapter extends ArrayAdapter<Company>
    private Activity activity;
    private LayoutInflater inflater = null;

    public CompanyAdapter (Activity activity, int textViewResourceId, List<Company> lCompany)
        super(activity, textViewResourceId, lCompany);
        try
            this.activity = activity;

            inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        catch (Exception e)
            e.printStackTrace();
        
    

    public Company getItem (Company position)
        return position;
    

    public  long getItemId(int position)
        return position;
    

    public  class ViewHolder 
        public TextView display_name;
    

    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
        View vi = convertView;
        final ViewHolder holder;
        try 
            if (convertView == null) 
                vi = inflater.inflate(R.layout.company_list_item, null);
                holder = new ViewHolder();

                holder.display_name = (TextView) vi.findViewById(R.id.tvCompanyName);


                vi.setTag(holder);
             else 
                holder = (ViewHolder) vi.getTag();
            
            holder.display_name.setText(getItem(position).getName());

         catch (Exception e) 
            e.printStackTrace();

        
        return vi;
    


名称字段的公司类

@SerializedName("name")
    private String name;

 public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

【问题讨论】:

我没有看到你已经实现了过滤器。它不会神奇地理解你究竟想如何过滤它 @VladyslavMatviienko As Ganesh 建议我已经实现了 ItemFilter,我可以看到传递给 publishResults 方法的结果,但是 notifyDataSetChanged 不起作用,List 没有更新为新结果。关于我可能遗漏的任何建议 【参考方案1】:

适配器必须implements Filterable,检查此示例

public class SearchableAdapter extends BaseAdapter implements Filterable 

    private List<String>originalData = null;
    private List<String>filteredData = null;
    private LayoutInflater mInflater;
    private ItemFilter mFilter = new ItemFilter();

    public SearchableAdapter(Context context, List<String> data) 
        this.filteredData = data ;
        this.originalData = data ;
        mInflater = LayoutInflater.from(context);
    

    public int getCount() 
        return filteredData.size();
    

    public Object getItem(int position) 
        return filteredData.get(position);
    

    public long getItemId(int position) 
        return position;
    

    public View getView(int position, View convertView, ViewGroup parent) 
        // A ViewHolder keeps references to children views to avoid unnecessary calls
        // to findViewById() on each row.
        ViewHolder holder;

        // When convertView is not null, we can reuse it directly, there is no need
        // to reinflate it. We only inflate a new View when the convertView supplied
        // by ListView is null.
        if (convertView == null) 
            convertView = mInflater.inflate(R.layout.list_item, null);

            // Creates a ViewHolder and store references to the two children views
            // we want to bind data to.
            holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.list_view);

            // Bind the data efficiently with the holder.

            convertView.setTag(holder);
         else 
            // Get the ViewHolder back to get fast access to the TextView
            // and the ImageView.
            holder = (ViewHolder) convertView.getTag();
        

        // If weren't re-ordering this you could rely on what you set last time
        holder.text.setText(filteredData.get(position));

        return convertView;
    

    static class ViewHolder 
        TextView text;
    

    public Filter getFilter() 
        return mFilter;
    

    private class ItemFilter extends Filter 
        @Override
        protected FilterResults performFiltering(CharSequence constraint) 

            String filterString = constraint.toString().toLowerCase();

            FilterResults results = new FilterResults();

            final List<String> list = originalData;

            int count = list.size();
            final ArrayList<String> nlist = new ArrayList<String>(count);

            String filterableString ;

            for (int i = 0; i < count; i++) 
                filterableString = list.get(i);
                if (filterableString.toLowerCase().contains(filterString)) 
                    nlist.add(filterableString);
                
            

            results.values = nlist;
            results.count = nlist.size();

            return results;
        

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) 
            filteredData = (ArrayList<String>) results.values;
            notifyDataSetChanged();
        

    


//in your Activity or Fragment where of Adapter is instantiated :

editTxt.addTextChangedListener(new TextWatcher() 

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) 
        System.out.println("Text ["+s+"]");

        mSearchableAdapter.getFilter().filter(s.toString());                           
    

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

    

    @Override
    public void afterTextChanged(Editable s) 
    
);

【讨论】:

嗨 Ganesh,我传递的列表不仅仅是字符串,它们是对象,在这种情况下 ItemFilter 怎么会不起作用。 ItemFilter 使用 List 而不是 List 的任何其他示例 我会相应修改并尝试 嗨@Ganesh Pokale,我已经实现了你所说的方式,并且在ItemFilter中它正在过滤数据并将results返回给piublishResults,但我认为notifyDataSetChanged()不起作用。虽然在 ItemFilter 中过滤了数据,但在 List 中没有更新数据 在 notifyDataSetChanged() 之前的 PublishResults 函数中,filteredData 有应该显示的正确数据,但列表没有刷新。 您是否检查了我的适配器中过滤数据列表的所有使用情况?就像在 public int getCount() return filteredData.size(); public Object getItem(int position) return filteredData.get(position);

以上是关于无法通过 ListView 搜索,返回零结果的主要内容,如果未能解决你的问题,请参考以下文章

为啥基于地理搜索/位置的搜索返回零结果?

如何在当前活动中将搜索结果保存在 ListView (Android) 中

在 Django 中无法从搜索栏呈现结果

Android 自定义 ListView onClickListener 返回 null

jQuery Mobile:Listview 过滤器搜索回调函数

使用 onlongClick 搜索 Listview 显示错误结果