Custom ListView Filter with own filtering logic.

In last blog, we show you pretty straightforward way to filter the list as user will type in text box. But it works only if we required string array adapter and we only want to filter the list using “contains” fashion.

But if we have our own custom data for array adapter then this may not work. With this approach, we can filter any custom data for array adapter and with our own filtering logic.

Here is the step-by-step way:

  1. Creating abstract class which will be extended by our custom DATA class.
    Name it It contains one abstract method which will implement our own custom filtering logic.

    public abstract class ListFilter 
    { public abstract boolean filterThisListItem(String prefix); }
  2. Changing ArrayAdapter class
    Use the power of open source :-). Copy the ArrayAdapter source code and make following changes.

    1. Template class of ArrayAdapter will extends the abstract class ListFilter created in first step.
    2. From line 485 through line 497 in ArrayAdapter class, it implements the default filtering logic. Change it to call template class own filtering logic. Based on that it will now filter the list.

We have created a package for this and you can use this package in your application. Please download the package from here.

How to use this package?

  1. Download the package and import the package into your application.
  2. Extend your data class to ListFilter class available in package.
  3. Implement your own filtering logic in filterThisListItem().

That’s it :-). Rest you have to do as usual which you do in ListActivity and ListAdapter.

1) Create layout XML as follows and name it chapter_list.xml:


2) Create your own data class which extends the ListFilter abstract class from package and write your own filtering logic:

public class CHAPTER extends ListFilter{
	public String name;
	public String path;
	public boolean filterThisListItem(String prefix) {
		return name.toLowerCase().startsWith(prefix.toLowerCase());

Here, we filter the list based on name of the chapter. For eg: If user types “a” in text box, all the chapters that starts with “a” will get filtered.

3) Activity class and Adapter

	ArrayList chapters;
	ChapterListAdapter adapter;
	public void onCreate(Bundle bundle){
		ListView list=(ListView)findViewById(;
		chapters=HelperXMLParser.parseSubjectToFetchChapters(this); //Here we parse the XML to retrieve the chapter list
		adapter=new ChapterListAdapter(this,R.layout.chapter_list_item,chapters);
		((EditText) findViewById(;


	private TextWatcher filterTextWatcher = new TextWatcher() {

	    public void afterTextChanged(Editable s) {

	    public void beforeTextChanged(CharSequence s, int start, int count,
	            int after) {

	    public void onTextChanged(CharSequence s, int start, int before,
	            int count) {

        //Adapter extends the FilterAdapter from package
        //Template class CHAPTER must extend ListFilter
	private class ChapterListAdapter extends FilterAdapter{
    	private class ViewWrapper{
    		TextView text;
    	public ChapterListAdapter(Context context, int textViewResourceId,
				List objects) {
			super(context, textViewResourceId, objects);
		public View getView(final int position, View convertView, ViewGroup parent) {
			View row=convertView;
			ViewWrapper wrapper=null;
				LayoutInflater inflater=(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				row=inflater.inflate(R.layout.chapter_list_item, null);
				wrapper=new ViewWrapper();

			row.setOnClickListener(new View.OnClickListener() {
				public void onClick(View v) {
					Intent intent=new Intent(ChapterListActivity.this,TopicListActivity.class);
					intent.putExtra(HelperApp.AppKey.CHAPTER_PATH, getItem(position).path);
					intent.putExtra(HelperApp.AppKey.CHAPTER_NAME, getItem(position).name);
			return row;