The solution ended up being a custom ArrayAdapter subclass which prepends a filter before the ArrayFilter even sees it.
The change to the main application is minimal, it just needs to instantiate the newly-christened WtfArrayAdapter and pass its constructor an extra argument: an object reference to the object containing the normalisation method (in the current äpp’s design, that’s the MainActivity class, a future refactor will do better):
- ArrayAdapter acronymKeys = new ArrayAdapter(this,
- android.R.layout.simple_list_item_1, sorted);
+ ArrayAdapter acronymKeys = new WtfArrayAdapter(this,
+ android.R.layout.simple_list_item_1, sorted, this);
The custom WtfArrayAdapter must be able to call methods from ArrayFilter (which is ArrayAdapter’s internal private class), so it needs to belong to package android.widget;. I’ll spare you the full imports, comments, etc. and will reproduce the important parts below:
public class WtfArrayAdapter<T> extends ArrayAdapter<T> {
New members for:
- the pre-filter normalisation method’s object
- our internal private class’ object
- the parent’s internal private class’ object (ArrayAdapter.mFilter is private, unfortunately)
private MainActivity sParent;
private WtfArrayFilter sFilter;
private Filter pFilter;
The extended constructor (we need to implement only the one we’re actually calling):
- call the inherited constructor
- store away the parent’s mFilter value
- instantiate our own WtfArrayFilter
- store away the pre-filter normalisation method’s object, as WtfArrayFilter will need it later
public WtfArrayAdapter(Context context, @LayoutRes int resource,
@NonNull T[] objects, MainActivity parent) {
super(context, resource, 0, Arrays.asList(objects));
sParent = parent;
sFilter = new WtfArrayFilter();
pFilter = super.getFilter();
}
Override ArrayAdapter’s getFilter() method to always return our new WtfArrayFilter:
public Filter getFilter() {
return sFilter;
}
Implementation of WtfArrayFilter as Filter subclass just like ArrayFilter does, and forwarding all boring (i.e. unchanged) calls to the inherited ArrayFilter:
private class WtfArrayFilter extends Filter {
protected void publishResults(CharSequence constraint,
FilterResults results) {
pFilter.publishResults(constraint, results);
}
We only need to change one method to do our own filtering before calling the inherited ArrayFilter’s filtering method:
protected FilterResults performFiltering(CharSequence prefix) {
return pFilter.performFiltering(prefix == null ? null :
sParent.normaliseAcronym(prefix.toString()));
}
}
}
Improvements welcome, I’m still a Java™ beginner.