How could i filter the listview using baseadapter

I am trying to filter the listview but getfilter method is not working,

here is the code:

@Override
public void afterTextChanged(Editable s) {
}

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

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
    mHistoryAdapter.getFilter().filter(s);   
}

i have added the method in baseadapter also

public Filter getFilter() {
    return null;
}

but its not working..could somebody help me out..@Thanks


MainActivity.java

public class MainActivity extends Activity {

private ListView mListView;
private CustomAdapter mCustomAdapter;
private EditText mEditText;
private ArrayList<Contacts> _Contacts = new ArrayList<Contacts>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    for (int i = 0; i < 100; i++) {
        Contacts contacts = new Contacts();
        contacts.setId(""+i);
        contacts.setName("Name "+i);
        _Contacts.add(contacts);
    }


    mListView = (ListView) findViewById(R.id.listView1);
    mEditText = (EditText) findViewById(R.id.editText1);

    mCustomAdapter = new CustomAdapter(MainActivity.this, _Contacts);
    mListView.setAdapter(mCustomAdapter);

    mEditText.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
            mCustomAdapter.getFilter().filter(arg0);
        }

        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                int arg3) {
        }

        @Override
        public void afterTextChanged(Editable arg0) {

        }
    });
}

}

CustomAdapter.java

public class CustomAdapter extends BaseAdapter implements Filterable{

private ArrayList<Contacts> _Contacts;
private Activity context;
private LayoutInflater inflater;
private ValueFilter valueFilter;
private ArrayList<Contacts> mStringFilterList;

public CustomAdapter(Activity context, ArrayList<Contacts> _Contacts) {
    super();
    this.context = context;
    this._Contacts = _Contacts;
    mStringFilterList =  _Contacts;
    this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
     getFilter();
}

@Override
public int getCount() {
    return _Contacts.size();
}

@Override
public Object getItem(int position) {
    return _Contacts.get(position).getName();
}

@Override
public long getItemId(int position) {
    return 0;
}

public class ViewHolder {
    TextView tname, tplace;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        holder = new ViewHolder();
        convertView = inflater.inflate(R.layout.activity_main, null);
        holder.tname = (TextView) convertView.findViewById(R.id.textView1);
        holder.tplace = (TextView) convertView.findViewById(R.id.textView2);
        convertView.setTag(holder);
    } else
        holder = (ViewHolder) convertView.getTag();
    holder.tname.setText("" + _Contacts.get(position).getName());
    holder.tplace.setText("" + "" + _Contacts.get(position).getId());
    return convertView;
}

@Override
public Filter getFilter() {
    if(valueFilter==null) {

        valueFilter=new ValueFilter();
    }

    return valueFilter;
}
private class ValueFilter extends Filter {

    //Invoked in a worker thread to filter the data according to the constraint.
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        FilterResults results=new FilterResults();
        if(constraint!=null && constraint.length()>0){
            ArrayList<Contacts> filterList=new ArrayList<Contacts>();
            for(int i=0;i<mStringFilterList.size();i++){
                if((mStringFilterList.get(i).getName().toUpperCase())
                        .contains(constraint.toString().toUpperCase())) {
                    Contacts contacts = new Contacts();
                    contacts.setName(mStringFilterList.get(i).getName());
                    contacts.setId(mStringFilterList.get(i).getId());
                    filterList.add(contacts);
                }
            }
            results.count=filterList.size();
            results.values=filterList;
        }else{
            results.count=mStringFilterList.size();
            results.values=mStringFilterList;
        }
        return results;
    }


    //Invoked in the UI thread to publish the filtering results in the user interface.
    @SuppressWarnings("unchecked")
    @Override
    protected void publishResults(CharSequence constraint,
            FilterResults results) {
        _Contacts=(ArrayList<Contacts>) results.values;
        notifyDataSetChanged();
    }
}
}

Contacts.java

public class Contacts {

private String name;
private String id;

public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public String getId() {
    return id;
}
public void setId(String id) {
    this.id = id;
}
}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<EditText
    android:id="@+id/editText1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ems="10" >

    <requestFocus />
</EditText>

<ListView
    android:id="@+id/listView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >
</ListView>

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:layout_marginLeft="1dp"
android:layout_marginRight="1dp"
android:layout_marginTop="2dp"
android:background="@android:color/black"
android:gravity="center_vertical"
android:paddingBottom="2dp"
android:paddingTop="2dp"
tools:context=".MainActivity" >


<TextView
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="8dp"
    android:text="Large Text"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:textColor="@android:color/white" />

<TextView
    android:id="@+id/textView2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="8dp"
    android:text="Small Text"
    android:textAppearance="?android:attr/textAppearanceSmall"
    android:textColor="@android:color/white" />

This is a sample project code. Use this code this will really help you


Here you go. A simple baseadapter (no view recycling) that will display, and filter, a list of some custom arbitary object. In this example Object.name is the field we will use to filter.

1) In your activity, (or) where you create your ListView, enable text filtering:

class MyObject {
    public String name;
}
List<MyObject> myData = ArrayList<>();

listview.setTextFilterEnabled(true);

2) As you already noted, in a textwatcher of an Edittext, trigger the filter on the ListAdapter:

public void onTextChanged(CharSequence s, int start, int before, int count) {
    listadapter.getFilter().filter(s);   
}

3) in your baseadapter, implement Filterable. And store two copies of the data, one original, and one filtered. Be sure to access the filtered data throughout the BaseAdapter, not the unfiltered data

public class FilterableListAdapterExample extends BaseAdapter implements Filterable {

private List<MyObject> mData; //the original data
private List<MyObject> mDataFiltered;//the filtered data
private LayoutInflater mLayoutInflater;

public FilterableListAdapterExample(Context context, List<MyObject> data) {
    mData = data;
    mDataFiltered=data;
    mLayoutInflater = LayoutInflater.from(context);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    convertView= mLayoutInflater.inflate(R.layout.listview_item, null);
    TextView textview=(TextView)convertView.findViewById(R.id.listitem_textview);
    //note: we access mDataFiltered, not mData
    textview.setText(mDataFiltered.get(position).name); 
    return convertView;
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public int getCount() {
    return mDataFiltered.size();
}

@Override
public Filter getFilter() {
    return new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();
            if (constraint == null || constraint.length() == 0) {
                //no constraint given, just return all the data. (no search)
                results.count = mData.size();
                results.values = mData;
            } else {//do the search
                List<MyObject> resultsData = new ArrayList<>();
                String searchStr = constraint.toString().toUpperCase();
                for (MyObject o : mData)
                    if (o.name.toUpperCase().startsWith(searchStr)) resultsData.add(o);
                results.count = resultsData.size();
                results.values = resultsData;
            }
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            mDataFiltered = (ArrayList<MyObject>) results.values;
            notifyDataSetChanged();
        }
    };
}

}


Please try following code it may helpful for you:

public class MainActivity extends ListActivity 
{

    private List<String> list = new ArrayList<String>();
    List<String> mOriginalValues;

    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        final MyAdapter adapter = new MyAdapter(this, getModel());
        setListAdapter(adapter);

        EditText filterEditText = (EditText) findViewById(R.id.filterText);

        // Add Text Change Listener to EditText
        filterEditText.addTextChangedListener(new TextWatcher() 
        {

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) 
            {
                // Call back the Adapter with current character to Filter
                adapter.getFilter().filter(s.toString());
            }

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

            @Override
            public void afterTextChanged(Editable s) 
            {
            }
        });
    }

    private List<String> getModel() {
        list.add("Linux");
        list.add("Windows7");
        list.add("Suse");
        list.add("Eclipse");
        list.add("Ubuntu");
        list.add("Solaris");
        list.add("Android");
        list.add("iPhone");
        list.add("Windows XP");
        return list;
    }

// Adapter Class            
public class MyAdapter extends BaseAdapter implements Filterable 
{

    List<String> arrayList;      
    List<String> mOriginalValues; // Original Values
    LayoutInflater inflater;

    public MyAdapter(Context context, List<String> arrayList) 
    {
        this.arrayList = arrayList;
        inflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() 
    {
        return arrayList.size();
    }

    @Override
    public Object getItem(int position) 
    {
        return position;
    }

    @Override
    public long getItemId(int position) 
    {
        return position;
    }

    private class ViewHolder 
    {
        TextView textView;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
    {

        ViewHolder holder = null;

        if (convertView == null) 
        {

            holder = new ViewHolder();
            convertView = inflater.inflate(R.layout.row, null);
            holder.textView = (TextView) convertView
                    .findViewById(R.id.listTxt);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.textView.setText(arrayList.get(position));
        return convertView;
    }

    @Override
    public Filter getFilter() 
    {
        Filter filter = new Filter() 
        {

            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint,FilterResults results) 
            {

                arrayList = (List<String>) results.values; // has the filtered values
                notifyDataSetChanged();  // notifies the data with new filtered values
            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) 
            {
                FilterResults results = new FilterResults();        // Holds the results of a filtering operation in values
                List<String> FilteredArrList = new ArrayList<String>();

                if (mOriginalValues == null) 
                {
                    System.out.println("");
                    mOriginalValues = new ArrayList<String>(arrayList); // saves the original data in mOriginalValues
                }

                /********
                 * 
                 *  If constraint(CharSequence that is received) is null returns the mOriginalValues(Original) values
                 *  else does the Filtering and returns FilteredArrList(Filtered)  
                 *
                 ********/
                if (constraint == null || constraint.length() == 0) 
                {

                    // set the Original result to return  
                    results.count = mOriginalValues.size();
                    results.values = mOriginalValues;
                } 
                else 
                {
                    constraint = constraint.toString().toLowerCase();
                    for (int i = 0; i < mOriginalValues.size(); i++) 
                    {
                        String data = mOriginalValues.get(i);
                        if (data.toLowerCase().startsWith(constraint.toString())) 
                        {
                            FilteredArrList.add(data);
                        }
                    }
                    // set the Filtered result to return
                    results.count = FilteredArrList.size();
                    results.values = FilteredArrList;
                }
                return results;
            }
        };
        return filter;
    }
}
}

Implement Filterable in your baseadapter class.

listview with search search listview

public class MainActivity extends AppCompatActivity {

String names[] = {"Apple","Banana","Kiwi","Oranges","Watermelon"};
String emails[] = {"This is apple","This is banana","This is kiwi","This is oranges","This is watermelon"};
int images[] = {R.drawable.apple,R.drawable.banana,R.drawable.kiwi,R.drawable.oranges,R.drawable.watermelon};

List<ItemsModel> itemsModelList = new ArrayList<>();

ListView listView;

CustomAdapter customAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    listView = findViewById(R.id.listview);


    for(int i = 0;i < names.length;i++){

        ItemsModel itemsModel = new ItemsModel(names[i],emails[i],images[i]);

        itemsModelList.add(itemsModel);

    }

     customAdapter = new CustomAdapter(itemsModelList,this);

    listView.setAdapter(customAdapter);


}


@Override
public boolean onCreateOptionsMenu(Menu menu) {


    getMenuInflater().inflate(R.menu.search_menu,menu);

    MenuItem menuItem = menu.findItem(R.id.searchView);

    SearchView searchView = (SearchView) menuItem.getActionView();

    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {

            Log.e("Main"," data search"+newText);

            customAdapter.getFilter().filter(newText);



            return true;
        }
    });


    return true;

}


@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {

    int id = item.getItemId();


    if(id == R.id.searchView){

        return true;
    }
    return super.onOptionsItemSelected(item);
}


public class CustomAdapter extends BaseAdapter implements Filterable {

    private List<ItemsModel> itemsModelsl;
    private List<ItemsModel> itemsModelListFiltered;
    private Context context;

    public CustomAdapter(List<ItemsModel> itemsModelsl, Context context) {
        this.itemsModelsl = itemsModelsl;
        this.itemsModelListFiltered = itemsModelsl;
        this.context = context;
    }



    @Override
    public int getCount() {
        return itemsModelListFiltered.size();
    }

    @Override
    public Object getItem(int position) {
        return itemsModelListFiltered.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        View view = getLayoutInflater().inflate(R.layout.row_items,null);


        TextView names = view.findViewById(R.id.name);
        TextView emails = view.findViewById(R.id.email);
        ImageView imageView = view.findViewById(R.id.images);

        names.setText(itemsModelListFiltered.get(position).getName());
        emails.setText(itemsModelListFiltered.get(position).getEmail());
        imageView.setImageResource(itemsModelListFiltered.get(position).getImages());

        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.e("main activity","item clicked");
                startActivity(new Intent(MainActivity.this,ItemsPreviewActivity.class).putExtra("items",itemsModelListFiltered.get(position)));

            }
        });

        return view;
    }



    @Override
    public Filter getFilter() {
        Filter filter = new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {

                FilterResults filterResults = new FilterResults();
                if(constraint == null || constraint.length() == 0){
                    filterResults.count = itemsModelsl.size();
                    filterResults.values = itemsModelsl;

                }else{
                    List<ItemsModel> resultsModel = new ArrayList<>();
                    String searchStr = constraint.toString().toLowerCase();

                    for(ItemsModel itemsModel:itemsModelsl){
                        if(itemsModel.getName().contains(searchStr) || itemsModel.getEmail().contains(searchStr)){
                            resultsModel.add(itemsModel);

                        }
                         filterResults.count = resultsModel.size();
                            filterResults.values = resultsModel;
                    }


                }

                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {

                itemsModelListFiltered = (List<ItemsModel>) results.values;
                notifyDataSetChanged();

            }
        };
        return filter;
    }
}

}

You can a full tutorial on how to implement listview with search and onItemClickListener here:

Listview with search/filter and onItemClickListener

Source files