Filtering list of apps in custom baseadapter

点点圈 提交于 2019-12-04 22:06:24

--

EDIT: I've developed a component which lets you filter custom ListViews and change filters dynamically etc. I think it has an easy implementation and you. Give it a try!

I hope this would be nicer for all of you.

https://github.com/matessoftwaresolutions/AndroidFilterableList

--

The easiest way for me:

  1. Define custom generic filter
  2. Define listeners required to make it generic
  3. Link all items to the view

Example:

  1. My extends baseAdapter implements the two interfaces (IFilteredItem and IFilteredListListener.

Its content is:

public class MenuListAdapter extends BaseAdapter implements IFilteredListListener<PointOfInterest>, IFilterableItem<PointOfInterest> {    
public MenuListAdapter(Context context,List<PointsOfInterest> points) {
        this.context = context;
        //Elements for the list
        this.points = points;
    }
....

BaseAdapter methods, and the other implementations:

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

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

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

@Override
public Filter getFilter() {
    if (filter == null) {
        filter = new ListFilter<PointOfInterest>(points, this, this,this);
    }
    return filter;
}

@Override
public void onSearchResult(List<PointOfInterest> objects) {
    if (objects.size() == 0) {
        points = objects;
        objects.add(mockedPointForEmptyList);
    } else {
        points = objects;
    }
}

@Override
public String getStringForFilter(PointOfInterest item) {
    return item.getTitle();
}
....

In my activity, I have a list view. I set my custom adapter, and it will compare an filter by the title of the point of interest:

In your activity, get the edit text which will be used to filter the list, and add the watcher:

filterText = (EditText) customActionBar.findViewById(R.id.searchText);
filterText.addTextChangedListener(filterTextWatcher);

In your activity (attribute zone), define your watcher:

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

};

I recommend you to use my own implementation of filter (copy and paste and let me know if you find any mistakes please!):

public class ListFilter<T> extends Filter {

private List<T> adapterFilterElements;
private List<T> originalFilterElements;
private final Object mLock = new Object();

private List<String> originalFilterValues;
private IFilteredListListener<T> listener;
private BaseAdapter baseAdapter;
private IFilterableItem<T> filterableItem;

public ListFilter(List<T> originalElements, BaseAdapter baseAdapter, IFilteredListListener<T> listener, IFilterableItem<T> filterableItem) {
    this.adapterFilterElements = originalElements;
    this.originalFilterElements = originalElements;
    this.baseAdapter = baseAdapter;
    this.listener = listener;
    this.filterableItem = filterableItem;
}

@Override
protected FilterResults performFiltering(CharSequence prefix) {
    FilterResults results = new FilterResults();
    if (originalFilterValues == null) {
        synchronized (mLock) {
            originalFilterValues = fillListNamesFromItems(adapterFilterElements);
        }
    }
    if (prefix == null || prefix.length() == 0) {
        ArrayList<String> list;
        synchronized (mLock) {
            list = new ArrayList<String>(originalFilterValues);
        }
        results.values = list;
        results.count = list.size();
    } else {
        String prefixString = prefix.toString().toLowerCase(Locale.UK);
        ArrayList<String> values;
        synchronized (mLock) {
            values = new ArrayList<String>(originalFilterValues);
        }
        final int count = values.size();
        final ArrayList<String> newValues = new ArrayList<String>();
        for (int i = 0; i < count; i++) {
            final String value = values.get(i);
            final String valueText = value.toString().toLowerCase(Locale.UK);
            // First match against the whole, non-splitted value
            if (valueText.startsWith(prefixString)) {
                newValues.add(value);
            } else {
                final String[] words = valueText.split(" ");
                final int wordCount = words.length;
                // Start at index 0, in case valueText starts with
                // space(s)
                for (int k = 0; k < wordCount; k++) {
                    if (words[k].startsWith(prefixString)) {
                        newValues.add(value);
                        break;
                    }
                }
            }
        }
        results.values = newValues;
        results.count = newValues.size();
    }
    return results;
}

@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
    results.values = fillItemListFromNames((List<String>) results.values);
    listener.onSearchResult((List<T>) results.values);
    adapterFilterElements = (List<T>) results.values;
    if (results.count > 0) {
        baseAdapter.notifyDataSetChanged();
    } else {
        baseAdapter.notifyDataSetInvalidated();
    }
}

private List<T> fillItemListFromNames(List<String> names) {
    List<T> ret = new ArrayList<T>();
    if (names != null) {
        for (String s : names) {
            for (T p : originalFilterElements) {
                if (filterableItem.getStringForFilter(p).equals(s)) {
                    ret.add(p);
                    break;
                }
            }
        }
    }

    return ret;
}

private List<String> fillListNamesFromItems(List<T> items) {
    List<String> ret = new ArrayList<String>();
    if (items != null) {
        for (T item : items) {
            ret.add(filterableItem.getStringForFilter(item));
        }
    }
    return ret;
}

}

The constructor receives a base adapter and two implementations of these custom interfaces:

public interface IFilteredListListener<T> extends Filterable {
public void onSearchResult(List<T> objects);

}

And

public interface IFilterableItem<T> {
public String getStringForFilter(T item);

}

Hope this concrete example helps!!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!