Question

In many places I've seen different ways of autocompletion, ones I considered very basic, others very well implemented.

My idea is having an AutoCompleteTextView but customizing its way of autocompletion. For example, all my autocompletion suggestions will be one-worded strings, where spaces are replaced by dashs (-). If I have a suggestion like last-night-I-was-bad, my goal would be that if the user enters one of the first letters of any word (I mean: l, n, I, w or b) the suggestion would be shown. Summarizing: treat dashes as spaces and showing the suggestions that match any substring of any 'word'. This kind of autocompletions I consider really useful!

I'd also be interested in discarding some of the characters from the suggestions. For example, suppose all my autosuggestions start with @, and the user enters the a letter, then all suggestions starting with @a would be shown.

Is there something like this, or at least is it possible to customize the way AutoCompleteTextView handles the suggestions? I had a look at the documentation but didn't see something like that (or at least, not as direct).

Any help appreciated!

Was it helpful?

Solution

Finally I got it. I made an ArrayAdapter extension, which has an internal Filter extension, and overriding performFiltering(CharSequence) and publishResults(CharSequence, FilterResults) I was able to implement the behavior I needed (basically compare two Strings using contains() instead of default startsWith()).

The code would be something like this, hope it may help someone.

public class SubstringFilterArrayAdapter<T> extends ArrayAdapter<T> implements Filterable {
  // Needed data structures
  ...
  final List<T> objects;
  final CustomFilter myfilter = new CustomFilter();
  ...

  public SubstringFilterArrayAdapter(final Context context_, final int tvResId_, final List<T> objects_) {
    objects = objects_;
    ...
  }

  @Override
  public Filter getFilter() {
    ...
  }

  private class CustomFilter extends Filter {
    @Override
    protected FilterResults performFiltering(final CharSequence prefix) {
      final FilterResults results = new FilterResults();
      final ArrayList<T> matched = new ArrayList<T>();


      // Put in matched the results that match the prefix using your own implementation
      ...

      results.values = matched;
      results.count = matched.size();

      return results;
    }

    @Override
    protected void publishResults(final CharSequence constraint, final FilterResults results) {
      objects = (List<T>) results.values;

      if (results.count > 0)
        notifyDataSetChanged();
      else
        notifyDataSetInvalidated();
    }
  }

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

  @Override
  public T getItem(int position) {
    return objects.get(position);
  }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top