搜索在 ArrayAdapter 和 ListView 中不起作用

Posted

技术标签:

【中文标题】搜索在 ArrayAdapter 和 ListView 中不起作用【英文标题】:Searching doesn't work in ArrayAdapter and ListView 【发布时间】:2015-06-14 22:38:13 【问题描述】:

不幸的是,我无法在 ArrayAdapter 内的 ListView 中实现搜索功能。 这是我的 MainActivity 的一部分:

    public class MainPageActivity extends ActionBarActivity implements View.OnClickListener 

        private static String TAG = "MainPageActivity";
        private ListView lv_medicines;
        private MedicineAdapter medicineAdapter;
        private JSONParser jsonParser;
        private List<Medicine> medicines;
        private EditText inputSearch;

        @Override
        protected void onCreate(Bundle savedInstanceState) 
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main_page);

            init();

            inputSearch.addTextChangedListener(new TextWatcher() 

                @Override
                public void afterTextChanged(Editable arg0) 
                

                @Override
                public void beforeTextChanged(CharSequence arg0, int arg1,
                                              int arg2, int arg3) 
                

                @Override
                public void onTextChanged(CharSequence cs, int arg1, int arg2,
                                          int arg3) 
                    MainPageActivity.this.medicineAdapter.getFilter().filter(cs);
                
            );

           /*...*/
        private void init() 
            lv_medicines = (ListView) findViewById(R.id.lv_medicines);
            lv_medicines.setTextFilterEnabled(true);
            inputSearch = (EditText) findViewById(R.id.inputSearch);


            medicineAdapter = new MedicineAdapter(getApplicationContext(), hatoanyagok);
            lv_medicines.setAdapter(medicineAdapter);
        

        /*...*/

    

这是我的 ArrayAdapter:

public class MedicineAdapter extends ArrayAdapter<String> implements Filterable

    private final Context context;
    private List<String> elements;
    private List<String> filteredData;

    public MedicineAdapter(Context context, List<String> elements) 
        super(context, R.layout.row_item, elements);
        this.context = context;
        this.elements = elements;
        this.filteredData = elements;
    

    public String getItem(int pos) 
        return filteredData.get(pos);
    

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

    public long getItemId(int position) 
        return position;
    

    public void deleteRow(String element) 
        if (filteredData.contains(element)) 
            filteredData.remove(element);
        
    

    public List<String> getObjects() 
        return filteredData;
    

    public void setObjects(List<String> objects) 
        this.elements = elements;
    

    public List<String> getValues() 
        return filteredData;
    

    private static class ViewHolder 
        TextView tv_medicine_name;
    

    public View getView(int position, View convertView, ViewGroup parent) 

        ViewHolder viewHolder;

        if (convertView == null) 
            viewHolder = new ViewHolder();
            LayoutInflater inflater = LayoutInflater.from(getContext());
            convertView = inflater.inflate(R.layout.row_item, parent, false);
            viewHolder.tv_medicine_name = (TextView) convertView.findViewById(R.id.tv_medicine_name);
            convertView.setTag(viewHolder);
         else 
            viewHolder = (ViewHolder) convertView.getTag();
        

        viewHolder.tv_medicine_name.setText(filteredData.get(position));


        return convertView;
    

    public void filter(String charText) 
        charText = charText.toLowerCase(Locale.getDefault());
        filteredData.clear();
        if (charText.length() == 0) 
            filteredData.addAll(elements);
        
        else
        
            for (String s : elements)
            
                if (s.toLowerCase(Locale.getDefault()).contains(charText))
                
                    filteredData.add(s);
                
            
        
        notifyDataSetChanged();
    

    public void notifyDataSetChanged() 
        super.notifyDataSetChanged();
    

会有什么问题? 提前感谢您的回答!

【问题讨论】:

什么不起作用?您是否尝试过在 filter() 方法中设置断点并在调试模式下运行应用程序? 从 MainPageActivity 的 onTextChanged() 方法不会从 ArrayAdapter 调用 filter() 方法。 getFilter() 方法在哪里定义的? 抱歉,我的代码有点不完整,但 Vikalp 的解决方案有效。感谢您的帮助。 【参考方案1】:

您需要再创建一个扩展 Filter

的类
public class filter_here extends Filter

private List<String> Original_Names;
private MedicineAdapter medicineAdapter;

public filter_here(List<String> Original_Names, MedicineAdapter ma)
    this.Original_Names = Original_Names;
    medicineAdapter = ma;


@Override
protected FilterResults performFiltering(CharSequence constraint) 
    // TODO Auto-generated method stub

    FilterResults Result = new FilterResults();
    // if constraint is empty return the original names
    if(constraint.length() == 0 )
        Result.values = Original_Names;
        Result.count = Original_Names.size();
        return Result;
    

    ArrayList<String> Filtered_Names = new ArrayList<String>();
    String filterString = constraint.toString().toLowerCase();
    String filterableString;

    for(int i = 0; i<Original_Names.size(); i++)
        filterableString = Original_Names.get(i);
        if(filterableString.toLowerCase().contains(filterString))
            Filtered_Names.add(filterableString);
        
    
    Result.values = Filtered_Names;
    Result.count = Filtered_Names.size();

    return Result;


@Override
protected void publishResults(CharSequence constraint,FilterResults results) 
    // TODO Auto-generated method stub
    medicineAdapter.setObjects((ArrayList<String>) results.values);
    medicineAdapter.notifyDataSetChanged();

在您的适配器中创建 filter_here 类的对象并将这一行添加到适配器的构造函数中

filterObj = new filter_here(elements, this);

同时改变你的适配器类的这个方法

public void setObjects(List<String> objects) 
    this.filteredData = objects;

将此方法添加到您的适配器

@Override
public Filter getFilter() 
    // TODO Auto-generated method stub
    return filterObj;

您的适配器中不需要过滤器方法。 其他一切保持原样。

【讨论】:

还有一个问题:如果我在适配器中到处使用元素变量而不是filteredData 会怎样?我需要过滤数据吗? 不,您不需要过滤数据。使用元素变量就足够了。

以上是关于搜索在 ArrayAdapter 和 ListView 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

为自定义 ArrayAdapter 实现 Fiterable 接口

ArrayAdapter 未在 ListView、Android Studio 中显示添加的元素

当我尝试使用 ArrayAdapter 时,我的应用程序崩溃了

android在使用ArrayAdapter时如何分配textViewResourceId

如何实现 Asynctask 在 ArrayAdapter 中加载图像

三种适配器:BaseAdapterSimpleAdapter和ArrayAdapter