natario1 / Autocomplete

Simple yet powerful autocomplete behavior for EditTexts, to avoid working with MultiAutoCompleteTextView APIs.
Apache License 2.0
357 stars 73 forks source link
android android-ui autocomplete autocompletetextview edittext popup

Build Status Release Issues

Need support, consulting, or have any other business-related question? Feel free to get in touch.

Like the project, make profit from it, or simply want to thank back? Please consider sponsoring me!

Autocomplete

Simple yet powerful autocomplete behavior for EditTexts, to avoid working with MultiAutoCompleteTextView APIs.

implementation("com.otaliastudios:autocomplete:1.1.0")

To see it in action, take a look at the sample app in the sample module.

Usage

Autocomplete let's you add autocomplete behavior to any EditText of your choice. The workflow is as follows:

These are the base components of the library. You will build an Autocomplete instance passing each component you need, and that's it.

Autocomplete.on(editText)
  .with(autocompletePolicy)
  .with(autocompleteCallback)
  .with(autocompletePresenter)
  .with(popupBackground)
  .with(popupElevation)
  .build();

AutocompletePolicy

This is an interface that controls when to show/hide the popup. For simple cases (single autocompletion, with just one result, similar to AutocompleteTextView) you can leave this unspecified. The library will fallback to Autocomplete.SimplePolicy:

public class SimplePolicy implements AutocompletePolicy {
    @Override
    public boolean shouldShowPopup(Spannable text, int cursorPos) {
        return text.length() > 0;
    }

    @Override
    public boolean shouldDismissPopup(Spannable text, int cursorPos) {
        return text.length() == 0;
    }

    @Override
    public CharSequence getQuery(Spannable text) {
        return text;
    }

    @Override
    public void onDismiss(Spannable text) {}
}

For more complex situations, you can go implementing the methods:

For the typical case of #hashtags, @usernames or whatever is triggered by a certain character, the library provides the CharPolicy class. It works as multi-autocomplete as well (e.g. for texts like you should see this @john @pete).

Autocomplete.on(editText)
  .with(new CharPolicy('#'))
  .with(autocompletePresenter)
  .build();

AutocompletePresenter

The presenter controls the display of items and their filtering when a query is selected. It is recommended to extend RecyclerViewPresenter, which shows a RecyclerView list. For more complex needs, look at the base AutocompletePresenter class and its comments.

Note: starting from 1.1.0, if the view returned by AutocompletePresenter has 0 height, this is read as a no-data signal and the popup will be dismissed. Not doing so would cause drawing artifacts, by leaving the popup in a weird state.

If you are performing asynchronous loading, make sure to give some height to your view, for example by returning a 'loading' item from your adapter, or adding vertical padding.

RecyclerViewPresenter

This automatically inflates a RecyclerView into the popup. Some relevant callbacks to be overriden:

When a list item is clicked, please ensure you are calling dispatchClick(item) to dispatch the click event to the AutocompleteCallback, if present.

AutocompleteCallback

public interface AutocompleteCallback<T> {
    boolean onPopupItemClicked(Editable editable, T item);
    void onPopupVisibilityChanged(boolean shown);
}

AutocompleteCallback controls what happens when either the popup visibility changes, or when an item is selected. Typically at this point you might want to insert a String related to that item into the EditText.

This should be done by acting on the Editable interface that you should already know, using methods like editable.insert() or editable.replace().

Contributing

You are welcome to contribute with issues, PRs or suggestions.