Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Custom ArrayAdapter doesn't refresh after filter

So I have a custom ArrayAdapter so I can use the Title/Subtitle view that is available on the ListView. I have an EditText that accepts a string and filters the adapter.

The filter works in the sense that it is filtering the correct objects (I can tell by clicking on it and it starts the intent with the correct "extras".)

However even though the filtering works, the items in the adapter are not updated to display the correct information... The title and subtitle are incorrect.

Lets say we have items 0 through 9 on the ListView, I filter to 3 items with a search, and lets say the filtered items are 5, 6, 9... 3 items are displayed, but its the first 3 items of the original pre-search ListView (0-2). If i click on the item 2 (the third item), the contents of 9 are contained in the new intent. This is correct for the search criteria, however the title did reflect the correct information.

I'm not sure what I need to tell the ListView to refresh. I don't think its notifyDataSetChanged();

Any help is appreciated. Thanks!

    public class myListAdapter extends ArrayAdapter<Pizza>{
    private ArrayList<Pizza> items;
    private PizzaViewHolder myListHolder;

    private class PizzaViewHolder{
        TextView title;
        TextView subtitle;
    }

    public myListAdapter(Context context, int textViewResourceId, ArrayList<Pizza> items) {
        super(context, textViewResourceId, items);
        this.items = items;
        // TODO Auto-generated constructor stub
    }

    @Override
    public View getView(int pos, View convertView, ViewGroup parent){
        View v = convertView;
        if(v == null){
            LayoutInflater vi = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(R.layout.myList_item, null);
            myListHolder = new PizzaViewHolder();
            myListHolder.title = (TextView)v.findViewById(R.id.title);
            myListHolder.subtitle = (TextView)v.findViewById(R.id.subtitle);
            v.setTag(myListHolder);
        }else myListHolder = (PizzaViewHolder)v.getTag();

        Pizza myList = items.get(pos);

        if (myList != null){
            myListHolder.title.setText(myList.getTitle());
            myListHolder.subtitle.setText(myList.getSubTitle());
        }       
        return v;           
    }
}

This is the search

    private TextWatcher filterTextWatcher = new TextWatcher(){

    public void afterTextChanged(Editable s) {
        // TODO Auto-generated method stub
        if(!s.equals("")){  
            ((Filterable) this.listView1.getAdapter()).getFilter().filter(s);
            }
    }

    public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {
        // TODO Auto-generated method stub

    }

    public void onTextChanged(CharSequence s, int start, int before,
            int count) {
        // TODO Auto-generated method stub

    }

};
like image 812
M Jesse Avatar asked Aug 07 '12 06:08

M Jesse


1 Answers

From what I have determined, it seems that I needed a custom Filter for my custom ArrayAdapter. The custom ArrayAdapter has an overridden implementation of Filter, here is the code:

import java.util.ArrayList;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.TextView;

public class PizzaAdapter extends ArrayAdapter<Pizza>{

private ArrayList<Pizza> original;
private ArrayList<Pizza> fitems;
private Filter filter;


public PizzaAdapter(Context context, int textViewResourceId, ArrayList<Pizza> items) {
    super(context, textViewResourceId, items);

    this.original = new ArrayList<Pizza>(items);
    this.fitems = new ArrayList<Pizza>(items);
    this.filter = new PizzaFilter();
}

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

    if(v == null){
        LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = vi.inflate(R.layout.pizza_list_item, null);
    }

    Pizza pizza = fitems.get(position);

    if(pizza != null){
        String subtitleString = new String("[" + pizza.getPizzaType() + "]   " + pizza.getPizzaCategory() + ": " + pizza.getPizzaCode());

        TextView title = (TextView)v.findViewById(R.id.title);
        TextView subtitle = (TextView)v.findViewById(R.id.subtitle);

        if(title != null){
            title.setText(pizza.getPizzaName());
        }
        if(subtitle != null){
            subtitle.setText(subtitleString);
        }
    }
    return v;
}

@Override
public Filter getFilter(){

    if(filter == null){
        filter = new PizzaFilter();
    }
    return filter;
}

private class PizzaFilter extends Filter{
    @Override
    protected FilterResults performFiltering(CharSequence constraint){
        FilterResults results = new FilterResults();
        String prefix = constraint.toString().toLowerCase();

        if (prefix == null || prefix.length() == 0){
            ArrayList<Pizza> list = new ArrayList<Pizza>(original);
            results.values = list;
            results.count = list.size();
        }else{
            final ArrayList<Pizza> list = new ArrayList<Pizza>(original);
            final ArrayList<Pizza> nlist = new ArrayList<Pizza>();
            int count = list.size();

            for (int i = 0; i<count; i++){
                final Pizza pizza = list.get(i);
                final String value = Pizza.getPizzaName().toLowerCase();

                if(value.contains(prefix)){
                    nlist.add(pizza);
                }
                results.values = nlist;
                results.count = nlist.size();
            }
        }
        return results;
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        fitems = (ArrayList<Pizza>)results.values;
        notifyDataSetChanged();
        clear();
        int count = fitems.size();
        for(int i = 0; i<count; i++){
            add(fitems.get(i));
            notifyDataSetInvalidated();
        }
    }
}
}

It turns out that a custom implmentation of Filter updated the display when you searched. Hopefully this will help some people.

like image 89
M Jesse Avatar answered Sep 20 '22 16:09

M Jesse