Skip to content

Instantly share code, notes, and snippets.

@fjfish
Created June 30, 2012 15:48
Show Gist options
  • Star 54 You must be signed in to star a gist
  • Fork 17 You must be signed in to fork a gist
  • Save fjfish/3024308 to your computer and use it in GitHub Desktop.
Save fjfish/3024308 to your computer and use it in GitHub Desktop.
Simple String Adapter for Android ListView that has a filter that gives whatever it finds and ignores word boundaries
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/list_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="16sp" >
</TextView>
package com.yourco.yourapp;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
// The standard text view adapter only seems to search from the beginning of whole words
// so we've had to write this whole class to make it possible to search
// for parts of the arbitrary string we want
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();
}
}
}
@sergioabril
Copy link

Hi, is it working? I might been using it in a wrong way.
Any help would be appreciated.

I'm calling it this way:

List datas = new ArrayList();
datas.add("France");
datas.add("localia");
datas.add("Rancia");

SearchableAdapter adapter = new SearchableAdapter(this, datas);
AddressBar.setAdapter(adapter);

But I'm getting:

07-18 02:01:38.160: E/AndroidRuntime(30618): java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
07-18 02:01:38.160: E/AndroidRuntime(30618): at SearchableAdapter.getCount(SearchableAdapter.java:42)

@sergioabril
Copy link

For some strange reason filteredData was null sometimes, causing the crash.
I solved changing this:

public int getCount() {
if(filteredData==null){
Log.v("LOG","Warn, null filteredData");
return 0;
}else{
return filteredData.size();
}
}

@iceone213
Copy link

Helped me a lot! thanks :)

@rupomkhondaker
Copy link

my list comes in a fragment. how can i implement this method there

@ganesh76
Copy link

your search functionality is working fine but your code makes list view empty when we remove all characters in search field. it should load all the default data again

@calebklc
Copy link

Thank you! This helped me a lot!

@huSSooxXx
Copy link

Thank you.. And another thanks to "eiprol" for editing

@prathibhaprabs
Copy link

prathibhaprabs commented Apr 25, 2017

Amazing!!! A small edit,
public int getCount() {
return filteredData == null ? 0 : filteredData.size();
}

Perfect now :)
But when I do BackSpace, it is sorting until it has at least one character. On deleting the entire data, drop down is not shown. and when I click it again drop down is not coming.

WHYYYYYYYYYYY???????

@prathibhaprabs
Copy link

@ganesh76 How do we show the default list when text is removed. Do you have any solution for this?

@maxmiliano
Copy link

@prathibhaprabs You must update the results.values with the reference to the original data.
I've done this with the code below, before the for:

        if (filterString.isEmpty()) {
            results.values = list;
            results.count = list.size();
            return results;
        }

@trifagabriel
Copy link

Thank you!!

@brunoperezm
Copy link

Thanks a lot!! This helped me so much!

@nithinkolekar
Copy link

Thanks
[simple star or follow button could have omitted this unwanted comment]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment