Android Studio:如何实现SearchView仅匹配列表项前5字符过滤ListView
实现仅匹配列表项前5个字符的搜索逻辑
你现在用的原生ArrayAdapter自带的过滤器默认会对列表项的完整内容做全字段模糊匹配,既没法满足「仅匹配前5个字符」的规则,还会因为两个Adapter独立过滤出现标题、答案错位的问题。按下面的步骤修改代码就能实现需求:
核心修改思路
- 保留原始的完整数据源,避免过滤过程中丢失全量数据
- 重写Adapter的过滤逻辑,匹配规则改为仅取每个标题条目的前5个字符和搜索关键词比对,遇到长度不足5个字符的条目自动取全字符串匹配,避免崩溃
- 过滤过程同步更新标题、答案两个一一对应的列表,从根源上避免错位
具体代码修改步骤
1. 新增成员变量存原始数据源
在Activity的成员变量区域新增两个列表,用来存从数据库读取的全量原始数据,不参与过滤操作:
// 存全量原始数据,作为过滤的基准数据源 private ArrayList<String> originalTitleList = new ArrayList<>(); private ArrayList<String> originalAnswerList = new ArrayList<>(); // 临时存过滤后的答案列表,同步更新第二个Adapter private ArrayList<String> filteredAnswerData = new ArrayList<>();
2. 读取数据库数据时同步写入原始列表
在onDataChange的循环读取逻辑里,把获取到的标题、答案同时存入原始列表:
for (DataSnapshot d : snapshot.getChildren()) { dream1 = d.getValue(Dream.class); String title = dream1.getTitle(); String answer = dream1.getAnswer(); // 存入原来Adapter绑定的列表 title_list.add(title); answer_list.add(answer); // 同步存入原始数据源 originalTitleList.add(title); originalAnswerList.add(answer); }
3. 重写Adapter的过滤逻辑,实现前5字符匹配
替换原来直接初始化arrayAdapter的代码,重写getFilter()方法,把匹配规则改成仅比对前5个字符,同时同步更新答案列表:
arrayAdapter = new ArrayAdapter<String>(this, R.layout.item, R.id.item, title_list) { @Override public Filter getFilter() { return new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); ArrayList<String> filteredTitles = new ArrayList<>(); filteredAnswerData.clear(); String query = constraint.toString().trim().toLowerCase(); // 搜索词为空时,直接展示全量数据 if (query.isEmpty()) { filteredTitles.addAll(originalTitleList); filteredAnswerData.addAll(originalAnswerList); } else { // 遍历全量原始数据做匹配 for (int i = 0; i < originalTitleList.size(); i++) { String itemTitle = originalTitleList.get(i); // 计算截取长度:最多取5个字符,不足5个就取全部,避免数组越界 int matchLength = Math.min(itemTitle.length(), 5); String frontPart = itemTitle.substring(0, matchLength).toLowerCase(); // 仅比对前5个字符的内容 if (frontPart.contains(query)) { filteredTitles.add(itemTitle); filteredAnswerData.add(originalAnswerList.get(i)); } } } results.values = filteredTitles; results.count = filteredTitles.size(); return results; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { // 更新标题列表的展示内容 title_list.clear(); title_list.addAll((ArrayList<String>) results.values); notifyDataSetChanged(); // 同步更新答案列表的展示内容,保证和标题一一对应 answer_list.clear(); answer_list.addAll(filteredAnswerData); arrayAdapter2.notifyDataSetChanged(); } }; } };
4. 简化SearchView的监听逻辑
原来的代码是分别给两个Adapter调用filter()方法,会导致两个列表独立筛选错位,现在因为过滤逻辑内部已经同步更新两个列表,只需要触发标题Adapter的过滤就行:
sr_txt.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { arrayAdapter.getFilter().filter(query); return false; } @Override public boolean onQueryTextChange(String newText) { arrayAdapter.getFilter().filter(newText); return false; } });
效果说明
- 严格按照前5个字符的规则匹配:哪怕搜索词出现在标题第6位及以后,也不会匹配到结果,完全符合需求
- 加了长度边界判断,不会因为某个标题长度不足5个字符触发索引越界崩溃
- 标题和答案列表全程按下标同步筛选,不会出现点击条目拿到的答案和标题不对应的错位问题
- 自动做了大小写不敏感处理,用户输入的内容不管大小写都能正常搜索
内容的提问来源于stack exchange,提问作者Abdul Salam
相关产品推荐
相关产品推荐

