Custom Listview Adapter with filter Android

You can use the Filterable interface on your Adapter, have a look at the example below:

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

Here are the links for the original source and another example

Leave a Comment