开发者

I have a ListView using a custom ArrayList adapter - what's the best way to implement filtering ? Anyone have a example code to study?

Subject says it all. I have seen examples implementing a custom Filter. The Android developer docs talk about implementing a Filterable interface. Does anyone have any advice and/or sample code on the best way to implement filtering开发者_如何学C in a ListView ?


This video comes from the latest Google I/O (2010), it's called "The world of ListView".

http://code.google.com/intl/it-IT/events/io/2010/sessions/world-of-listview-android.html

at 34:25 it explains how to implement a text filter

here, near line 437, an example of use:

https://github.com/android/platform_frameworks_base/blob/master/core/java/android/widget/ArrayAdapter.java

enjoy :)


Since this was the first answer I have found on google I decided to post some code to save the next person some time. I have come up with the code thanks to this blog: http://www.mokasocial.com/2010/07/arrayadapte-filtering-and-you/

public void buildSearchList {
 lv2 = new ListView(this);
 edi = new EditText(this);

 edi.setHint(R.string.teclear);
 edi.addTextChangedListener(filterTextWatcher);
 lv2.addFooterView(cancelButton);
 lv2.addHeaderView(edi);
 lv2.setAdapter(mAdapter2);
 lv2.setTextFilterEnabled(true);
}

private class EventAdapter extends ArrayAdapter<Articulo> implements
        Filterable {

    public ArrayList<Articulo> mEvents = null;

    private final Object mLock = new Object();
    private Filter filter;

    public EventAdapter(Context c, ArrayList<Articulo> clientes) {
        super(c, android.R.layout.test_list_item);
        mContext = c;

        mEvents = clientes;
        filter = new MyFilter();
    }

    @Override
    public Filter getFilter() {
        if (filter == null) {
            filter = new MyFilter();
        }
        return filter;
    }

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

    public Articulo getItem(int position) {
        return mEvents.get(position);
    }

    public long getItemId(int position) {
        return mEvents.get(position).getIdCodigo();
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        EventEntryView btv;
        if (convertView == null) {
            btv = new EventEntryView(mContext, mEvents.get(position));

        } else {
            btv = (EventEntryView) convertView;
            String title1 = mEvents.get(position).getDescripcion();

            if (title1 != null) {
                btv.setText1Title(title1);
            }

        }

        btv.setBackgroundColor(Color.BLACK);
        return btv;

    }

    private Context mContext;

    private class MyFilter extends Filter {

        protected FilterResults performFiltering(CharSequence prefix) {
            // Initiate our results object
            FilterResults results = new FilterResults();
            // Collection<? extends Articulo> mItemsArray = null;
            // If the adapter array is empty, check the actual items array
            // and use it
            if (mEvents == null) {
                synchronized (mLock) { // Notice the declaration above

                    if(cual==1)
                    mEvents = new ArrayList<Articulo>(clientes);
                    else mEvents = new ArrayList<Articulo>(ventas);
                }
            }
            // No prefix is sent to filter by so we're going to send back
            // the original array
            if (prefix == null || prefix.length() == 0) {
                synchronized (mLock) {
                    if(cual==1){
                    results.values = clientes;
                    results.count = clientes.size();
                    }else {
                        results.values = ventas;
                        results.count = ventas.size();
                    }

                }
            } else {
                // Compare lower case strings
                String prefixString = prefix.toString().toLowerCase();
                // Local to here so we're not changing actual array
                final ArrayList<Articulo> items = mEvents;
                final int count = items.size();
                final ArrayList<Articulo> newItems = new ArrayList<Articulo>(
                        count);
                for (int i = 0; i < count; i++) {
                    final Articulo item = items.get(i);
                    final String itemName = item.getDescripcion()
                            .toString().toLowerCase();
                    // First match against the whole, non-splitted value
                    if (itemName.startsWith(prefixString)) {
                        newItems.add(item);
                    } else {
                        // else {} // This is option and taken from the
                        // source of
                        // ArrayAdapter
                        final String[] words = itemName.split(" ");
                        final int wordCount = words.length;
                        for (int k = 0; k < wordCount; k++) {
                            if (words[k].startsWith(prefixString)) {
                                newItems.add(item);
                                break;
                            }
                        }
                    }
                }

                // Set and return
                results.values = newItems;
                results.count = newItems.size();
            }
            return results;
        }

        @SuppressWarnings("unchecked")
        protected void publishResults(CharSequence prefix,
                FilterResults results) {
            // noinspection unchecked
            mEvents = (ArrayList<Articulo>) results.values;
            // Let the adapter know about the updated list
            if (results.count > 0) {
                notifyDataSetChanged();
            } else {
                notifyDataSetInvalidated();
            }
        }

    }


}


 private class EventEntryView extends LinearLayout {

    private TextView text1;

    public EventEntryView(Context context, Articulo subSolicitud) {
        super(context);
        this.setOrientation(VERTICAL);

        text1 = new TextView(context);
        text1.setTextSize(20);
        text1.setPadding(10, 20, 10, 20);
        text1.setTextColor(Color.WHITE);
        String t = subSolicitud.getDescripcion();
        text1.setText(t);

        addView(text1, new LinearLayout.LayoutParams(
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

    }

    public void setText1Title(String title1) {
        text1.setText(title1);
    }
}

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) {
        mAdapter2.getFilter().filter(s);
    }

};


There are two possible ways of Resolving this

1. Use your own Filtering Algorithm to filter the adapter(As said by others). 2. The second and much simpler method is to override the tostring method in the Custom RowItem class you might have defined

 @Override
        public String toString() {
            return name + "\n" + description;
        }

where name and description are the possible text you have stored in the row items on which you want filtering

and use the adapter.getFilter().filter(s); as such you were using it will work now because your adapter now returns a valid string to filter


I looked at some sample code from other developers and learned a lot by simply reading through the source for ArrayAdapter. Armed with that info I managed to implement my own filtering.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜