android – filter listview with image and text view using custom adapter-ThrowExceptions

Exception or error:

I have a listview in my app, which looks like this:

–img– –ArrayListItems(names)— —TextView—-

I am using Action bar sherlock with search view to make the app reverse compatible.
I am using custom adapter which extends Base Adapter and also implements filterable. What i actually need is, when the user types in the text in the search bar, i should be able to filter the list view based on ArrayListItems(names). I refered several posts on stackoverflow, tried all code snippets. but still i am unable to search. When i run the the code, search bar does nothing.

In my activity I did:

public class SearchViewActionBar extends SherlockActivity implements SearchView.OnQueryTextListener 
{
    public SearchView mSearchView;
    private TextView mStatusView;
    int mSortMode = -1;


    protected CharSequence[] _options = { "Wild Life", "River", "Hill Station", "Temple", "Bird Sanctuary", "Hill", "Amusement Park"};
    protected boolean[] _selections =  new boolean[ _options.length ];


    private final String[] mStrings = Cheeses.sCheeseStrings;

    ListView lv1; 

    ItemListBaseAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_ACTION_BAR);

        setContentView(R.layout.activity_main);


       ArrayList<ItemDetails> image_details = GetSearchResults();
       lv1= (ListView) findViewById(R.id.list_view);

       adapter=new ItemListBaseAdapter(this, image_details);

        lv1.setAdapter(adapter);
        lv1.setTextFilterEnabled(true);


        mSearchView = (SearchView) findViewById(R.id.action_search);


        /*lv1.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> a, View v, int position, long id) { 
                Object o = lv1.getItemAtPosition(position);
                ItemDetails obj_itemDetails = (ItemDetails)o;
                //Toast.makeText(ListViewImagesActivity.this, "You have chosen : " + " " + obj_itemDetails.getName(), Toast.LENGTH_LONG).show();
            }  
        });*/


    }


    private ArrayList<ItemDetails> GetSearchResults()
    {
        ArrayList<ItemDetails> results = new ArrayList<ItemDetails>();


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

        ItemDetails item_details = new ItemDetails();
        item_details.setName(mStrings[i]);
        item_details.setItemDescription("200");
        results.add(item_details);
        }


        return results;
    }

    private void setupSearchView() {
        mSearchView.setIconifiedByDefault(true);
        mSearchView.setOnQueryTextListener(this);
        mSearchView.setSubmitButtonEnabled(false);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
    {
        super.onCreateOptionsMenu(menu);

        MenuInflater inflater = getSupportMenuInflater();
        inflater.inflate(R.menu.searchview_in_menu, menu);
        MenuItem searchItem = menu.findItem(R.id.action_search);
        mSearchView = (SearchView) searchItem.getActionView();

       setupSearchView();

        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) 
    {
        if (mSortMode != -1) 
        {
            //Drawable icon = menu.findItem(mSortMode).getIcon();
            //menu.findItem(R.id.action_sort).setIcon(icon);
        }
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
    {


    switch (item.getItemId()) {
        //case R.id.action_search:
            //finish();
            //getSupportActionBar().setDisplayShowHomeEnabled(false);
            //getSupportActionBar().setDisplayShowTitleEnabled(false);
            //System.out.println("search pressed");
            //break;
        case R.id.action_edit:
            System.out.println("category pressed");
            showDialog( 0 );
            //finish();
            break;
        default:
            //return super.onOptionsItemSelected(item);
            break;
        }

        /*
        String c="Category";
        if(s.equals(c))
        {
            System.out.println("same");
            ;
        }*/

        //Toast.makeText(this, "Selected Item: " + item.getTitle(), Toast.LENGTH_SHORT).show();
        return true;
    }

    protected Dialog onCreateDialog( int id ) 
    {
        return 
        new AlertDialog.Builder( this )
            .setTitle( "Category" )
            .setMultiChoiceItems( _options, _selections, new DialogSelectionClickHandler() )
            .setPositiveButton( "SAVE", new DialogButtonClickHandler() )
            .create();
    }


    public class DialogSelectionClickHandler implements DialogInterface.OnMultiChoiceClickListener
    {
        public void onClick( DialogInterface dialog, int clicked, boolean selected )
        {
            Log.i( "ME", _options[ clicked ] + " selected: " + selected );
        }
    }


    public class DialogButtonClickHandler implements DialogInterface.OnClickListener
    {
        public void onClick( DialogInterface dialog, int clicked )
        {
            switch( clicked )
            {
                case DialogInterface.BUTTON_POSITIVE:
                    printSelectedPlanets();
                    break;
            }
        }
    }

    protected void printSelectedPlanets()
    {
        for( int i = 0; i < _options.length; i++ ){
            Log.i( "ME", _options[ i ] + " selected: " + _selections[i] );
        }
    }

    public void onSort(MenuItem item) 
    {
        mSortMode = item.getItemId();
        invalidateOptionsMenu();
    }


    public boolean onQueryTextChange(String newText) 
    {


        /*ActionBar ab = getSupportActionBar(); 
        ab.setDisplayShowTitleEnabled(false); 
        ab.setDisplayShowHomeEnabled(false);*/

        //getSupportActionBar().setDisplayShowHomeEnabled(false);
        //getSupportActionBar().setDisplayShowTitleEnabled(false);

        if (TextUtils.isEmpty(newText)) 
        {
            System.out.println("empty query");
            lv1.clearTextFilter();
        } 
        else 
        {
            //System.out.println(newText.toString());

            adapter.getFilter().filter(newText);
            //adapter.getFilter().filter(s);

            //lv1.setFilterText(newText.toString());
        }
        return true;
    }

    public boolean onQueryTextSubmit(String query) 
    {
        mStatusView.setText("Query = " + query + " : submitted");
        return false;
    }

    public boolean onClose() 
    {
        mStatusView.setText("Closed!");
        return false;
    }

    protected boolean isAlwaysExpanded() 
    {
        return false;
    }
}

My adapter class:

public class ItemListBaseAdapter extends BaseAdapter implements Filterable
{
    private static ArrayList<ItemDetails> itemDetailsrrayList,list;

    private Integer[] imgid = {
            //R.drawable.p1,
            R.drawable.bb2,
            /*R.drawable.p2,
            R.drawable.bb5,
            R.drawable.bb6,
            R.drawable.d1*/
            };

    private LayoutInflater l_Inflater;

    public ItemListBaseAdapter(Context context, ArrayList<ItemDetails> results) {
        itemDetailsrrayList = results;
        l_Inflater = LayoutInflater.from(context);
    }

    public int getCount() {
        return itemDetailsrrayList.size();
    }

    public Object getItem(int position) {
        return itemDetailsrrayList.get(position);
    }

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

    public View getView(int position, View convertView, ViewGroup parent) 
    {
        ViewHolder holder;
        if (convertView == null) {
            convertView = l_Inflater.inflate(R.layout.item_details_view, null);
            holder = new ViewHolder();
            holder.txt_itemName = (TextView) convertView.findViewById(R.id.textView1);
            holder.txt_itemDescription = (TextView) convertView.findViewById(R.id.textView2);
            //holder.txt_itemPrice = (TextView) convertView.findViewById(R.id.phone);
            holder.itemImage = (ImageView) convertView.findViewById(R.id.imageView1);

            convertView.setTag(holder);
        } else 
        {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.txt_itemName.setText(itemDetailsrrayList.get(position).getName());
        //holder.txt_itemDescription.setText(itemDetailsrrayList.get(position).getItemDescription());
        holder.txt_itemDescription.setText("200");

        //holder.txt_itemPrice.setText(itemDetailsrrayList.get(position).getPrice());
        //holder.itemImage.setImageResource(imgid[itemDetailsrrayList.get(position).getImageNumber() - 1]);

        holder.itemImage.setImageResource(imgid[0]);

        return convertView;
    }

    static class ViewHolder 
    {
        TextView txt_itemName;
        TextView txt_itemDescription;
        //TextView txt_itemPrice;
        ImageView itemImage;
    }

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

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

                list = (ArrayList<ItemDetails>) 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 (list == null) {
                    list = new ArrayList<ItemDetails>(list); // 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 = list.size();
                    results.values = list;
                } else {
                    constraint = constraint.toString().toLowerCase();
                    for (int i = 0; i < list.size(); i++) 
                    {
                        String data="b";
                        //= list.getName(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;
    }

}
How to solve:

I had posted an answer here: https://stackoverflow.com/a/12363961/450534 that was based on a question of mine a few days back here: Filtering a ListView with Baseadapter filters text not images.

The problem I was facing in the question was that the text would get filtered by the images would not match. The answer posted takes care of that problem. The solution, as also mentioned in the answer, is for a GridView but works just perfect with a ListView too.

It is a mighty lengthy answer so I am simply linking instead of re-posting it here. It has the entire solution BTW and should help you just fine.

###

You have to add a TextWatcher to your searchView something like below:

mSearchView.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
    adapter.getFilter().filter(s);
}}

Note:

The Filter use toString method of your ItemDetails class. You have to override toString for filtering.

Leave a Reply

Your email address will not be published. Required fields are marked *