Getfilter() On A Custom Arrayadapter Not Working
Solution 1:
ArrayAdapter
's built-in Filter
uses the toString()
return from the model class (i.e., its type parameter) to perform its filtering comparisons. You don't necessarily need a custom Filter
implementation if you're able to override User
's toString()
method to return what you want to compare (provided its filtering algorithm is suitable to your situation). In this case:
@OverridepublicStringtoString() {
return name;
}
To be clear on exactly what that algorithm is, ArrayAdapter
's default filtering goes as follows:
The filter String
is first converted to lowercase. Then, looping over the dataset, each value's toString()
return is converted to lowercase, and checked to see if it startsWith()
the filter String
. If so, it's added to the result set. If not, a second check is performed, whereby the value's lowercase String
is split on a space (" "
), and each value from that is compared to the filter, again using startsWith()
. Basically, it first checks if the whole thing starts with the filter text, and then checks each word, if necessary.
If that's a suitable filter, then this solution is by far the simplest.
If that does not meet your needs, and you do actually need a custom Filter
implementation, then you should just not use ArrayAdapter
to begin with. ArrayAdapter
maintains internal, private List
s for the original and filtered collections – initially populated from the collection passed in the constructor call – and you do not have access to those. This is why the custom Filter
attempt shown does not work, as the displayed item count and the item returned from getItem(position)
are coming from that internal filter List
, not the one built in the custom Filter
.
In that case, you should directly subclass BaseAdapter
instead, maintaining your own List
s for the original and filtered collections. You can use ArrayAdapter
's source as a guide.
Indeed, ArrayAdapter
is often the wrong choice when choosing an Adapter
to extend. ArrayAdapter
is designed for a singular, somewhat simplistic goal: setting a flat String
on a single TextView
in each list item. There are several cases in which subclassing ArrayAdapter
instead of BaseAdapter
is rather pointless and/or redundant. For example:
- Overriding
getView()
and not using theView
returned from a call tosuper.getView()
. - Manually setting the text on the
TextView
yourself, for whatever reason. - Maintaining and using your own collections; i.e., the arrays, or
List
s, or what have you.
In these and certain other cases, it's arguably better to use BaseAdapter
from the start. Using ArrayAdapter
for anything much more complex than single text items with basic functionality can quickly become cumbersome and error-prone, and is often more trouble than it's worth.
Lastly, I would mention that ListView
is basically deprecated, at this point, though not yet officially, at the time of this writing. Current recommendations are to use RecyclerView
instead. However, for those brand new to Android programming, ListView
can still be useful as a beginning step in understanding the overall design of this type of recycling adapter View
. RecyclerView
can be a little overwhelming to start with.
Solution 2:
FiltermyFilter=newFilter() {
@Overrideprotected FilterResults performFiltering(CharSequence constraint) {
FilterResultsfilterResults=newFilterResults();
ArrayList<User> tempList=newArrayList<User>();
// Add the filter code hereif(constraint != null && users!=null) {
int length= users.size();
int i=0;
while(i<length){
User item= users.get(i);
//do whatever you wanna do here//adding result set output array if() { // Add check here, and fill the tempList which shows as a result
tempList.add(item);
}
i++;
}
//following two lines is very important//as publish result can only take FilterResults users
filterResults.values = tempList;
filterResults.count = tempList.size();
}
return filterResults;
}
@SuppressWarnings("unchecked")@OverrideprotectedvoidpublishResults(CharSequence contraint, FilterResults results) {
users = (ArrayList<User>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
Lastly, Override this method and return filter instance.
@OverridepublicFiltergetFilter() {
return myFilter;
}
For more reference see https://gist.github.com/tobiasschuerg/3554252
Post a Comment for "Getfilter() On A Custom Arrayadapter Not Working"