ListView搜索过滤失效排查:项为含双字符串的Word对象
The issue boils down to how the default ArrayAdapter handles filtering. It uses the toString() method of your Word objects to check for matches, but since you haven’t overridden this method in the Word class, it uses the default Object.toString() implementation. That returns a string like com.yourpackage.Word@abc123—nothing related to your actual Swedish or English text. So when you type a search query, none of your items match, hence everything disappears.
toString() Override This is the simplest way to get your search working. Update your Word class to include a toString() method that combines both language fields. This lets the filter check against either text:
public class Word { private String swedish; private String english; // ... existing constructor, getters, and setters ... @Override public String toString() { // Combine both languages so searching either will find the item return swedish + " " + english; } }
If you want more flexibility (like case-insensitive searches, exact matches, or prioritizing one language over the other), implement a custom filter in your CheckListAdapter. Here’s how:
First, add variables to track the original and filtered data in your adapter:
public class CheckListAdapter extends ArrayAdapter<Word> { private static final String TAG = "CheckListAdapter"; private Context mContext; private int mResource; private int lastPosition = -1; private ArrayList<Word> originalList; // Stores the full unfiltered dataset private ArrayList<Word> filteredList; // Stores results after filtering // Update constructor to initialize our list variables public CheckListAdapter(@NonNull Context context, int resource, @NonNull ArrayList<Word> objects, Context mContext) { super(context, resource, objects); this.mContext = mContext; mResource = resource; this.originalList = new ArrayList<>(objects); this.filteredList = new ArrayList<>(objects); } // ... existing getView method remains the same ... // Override getFilter to use our custom logic @Override public Filter getFilter() { return new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); ArrayList<Word> tempList = new ArrayList<>(); if (constraint == null || constraint.length() == 0) { // No filter applied: use the full original list tempList.addAll(originalList); } else { String query = constraint.toString().toLowerCase().trim(); // Check if query matches either Swedish or English text for (Word word : originalList) { if (word.getSwedish().toLowerCase().contains(query) || word.getEnglish().toLowerCase().contains(query)) { tempList.add(word); } } } results.values = tempList; results.count = tempList.size(); return results; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { filteredList.clear(); filteredList.addAll((ArrayList<Word>) results.values); notifyDataSetChanged(); // Refresh the ListView with filtered data } }; } // Override these methods to use our filtered list instead of the super class's default @Override public Word getItem(int position) { return filteredList.get(position); } @Override public int getCount() { return filteredList.size(); } }
- Solution 1 tricks the default filter into checking your actual text by providing a meaningful
toString()value. - Solution 2 gives you full control over filtering logic—you can tweak how matches are detected, handle case sensitivity, or even add advanced rules like partial matches in specific fields.
Either approach will fix your disappearing ListView items when searching. Start with Solution 1 for a fast fix, or go with Solution 2 if you need more customization.
内容的提问来源于stack exchange,提问作者Alex Rodionow

