Пользовательское поведение AutoCompleteTextView - PullRequest
8 голосов
/ 27 января 2012

Из коробки виджет AutoCompleteTextView не может соответствовать входной строке в середине значения списка - совпадения всегда выполняются в начале;например, ввод "ar" соответствует "argentina", но не "hungary".

Как мне найти текст в середине слова?Кто-нибудь может дать мне идею?

Заранее спасибо!

Ответы [ 4 ]

7 голосов
/ 27 января 2012

Вам нужно написать собственный класс Filter и реализовать метод performFiltering самостоятельно. Этот метод принимает аргумент CharSequence, который вы можете использовать для выполнения любых операций String, которые вам нужны, чтобы сгенерировать список совпадений из вашего набора данных (в вашем случае вы могли бы использовать String.contains вместо String.startsWith). Функция performFiltering не выполняется в потоке пользовательского интерфейса.

Затем вы возвращаете свой список совпадений в виде объекта FilterResults, который содержит Object значений (ваш список совпадений, вероятно, ArrayList) и int count , который является размером вашего списка матчей.

Наконец, реализуйте метод обратного вызова publishResults, который возвращает, как только рабочий поток сгенерирует список совпадений, позволяя вам вызвать notifyDataSetChanged на адаптере вашего AutoCompleteTextView, чтобы он мог отображать результаты .

4 голосов
/ 08 мая 2015

Старый вопрос, но все еще актуален.Следуя указаниям нескольких других вопросов, реализован пользовательский адаптер с использованием фильтруемого.Я сделал простой универсальный адаптер, который выполняет поиск с содержанием.Краткие заметки об этом:

Я использую нож, но легко сделать viewHolder с помощью findviewbyid.

Макет R.layout.list_item_simple - это простой макет с textview R.id.text_view_simple.

Для объекта требуется сопоставить строку toString.

public class SimpleContainsAutocompleteAdapter <T> extends ArrayAdapter<T> implements Filterable {
    private List <T> listObjects;
    List<T> suggestions = new ArrayList<>();
    private int resource;

    private Filter mFilter = new Filter(){
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults filterResults = new FilterResults();

            if(constraint != null) {
                suggestions.clear();
                for(T object : listObjects){
                    if(object.toString().toLowerCase().contains(constraint.toString().toLowerCase())){
                        suggestions.add(object);
                    }
                }

                filterResults.values = suggestions;
                filterResults.count = suggestions.size();
            }

            return filterResults;
        }

        @Override
        protected void publishResults(CharSequence contraint, FilterResults results) {
            if(results == null){
                return;
            }

            List<T> filteredList = (List<T>) results.values;
            if(results.count > 0) {
                clear();
                for (T filteredObject : filteredList) {
                    add(filteredObject);
                }
                notifyDataSetChanged();
            }
        }
    };

    public SimpleContainsAutocompleteAdapter(Context context, List<T> listObjects) {
        super(context, R.layout.list_item_simple, listObjects);
        this.listObjects = new ArrayList<>(listObjects);
        this.resource = R.layout.list_item_simple;
    }

    @Override
    public Filter getFilter() {
        return mFilter;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Object listObject = getItem(position);
        viewHolder holder;
        if(convertView != null) {
            holder = (viewHolder) convertView.getTag();
        }else{
            convertView = LayoutInflater.from(getContext()).inflate(resource, parent, false);
            holder = new viewHolder(convertView);
            convertView.setTag(holder);
        }

        holder.name.setText(listObject.toString());

        return convertView;
    }


    static class viewHolder {
        @InjectView(R.id.text_view_simple) TextView name;

        public viewHolder(View view) {
            ButterKnife.inject(this, view);
        }
    }
}
2 голосов
/ 25 августа 2015
public class AutoCompleteAdapter <T> extends ArrayAdapter<T> implements Filterable {
    private List <T> listObjects;
    List<T> suggestions = new ArrayList<>();
    private Context context;
    public AutoCompleteAdapter(Context context, List<T> listObjects) {
        super(context, R.layout.list_item_simple, listObjects);
        this.listObjects = new ArrayList<>(listObjects);
        this.context = context;
    }
    private Filter mFilter = new Filter(){
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults filterResults = new FilterResults();
            if(constraint != null) {
            suggestions.clear();
                for(T object : listObjects){  
                    if(object.toString().toLowerCase().contains(constraint.toString().toLowerCase())){                        suggestions.add(object);
                }
            }

            filterResults.values = suggestions;
            filterResults.count = suggestions.size();
        }
        return filterResults;
    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        if(results == null){
            return;
        }
        List<T> filteredList = (List<T>) results.values;
        if(results.count > 0) {
            clear();
            for (T filteredObject : filteredList) {
                add(filteredObject);
            }
            notifyDataSetChanged();
        }
    }
};
@Override
public Filter getFilter() {
    return mFilter;
}
private static class ViewHolder {
    TextView title;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    Object listObject = getItem(position);
    final ViewHolder viewHolder; // view lookup cache stored in tag
    if (convertView == null) {
        viewHolder = new ViewHolder();
        LayoutInflater inflater = LayoutInflater.from(getContext());
        convertView = inflater.inflate(R.layout.list_item_simple, parent, false);
        viewHolder.title = (TextView) convertView.findViewById(R.id.title);
        convertView.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) convertView.getTag();
    }
    viewHolder.title.setText(listObject.toString());
    return convertView;
}

}

0 голосов
/ 02 июля 2012

Мой совет - разобрать строку в массив символов. Затем повторяйте каждый символ, пока строка не будет найдена.

Например, предположим, что ваш поиск хотел вернуть все слова с "ate", а список слов был ...

состояние черта характера бранить поздно

Ваш алгоритм должен выглядеть примерно так

Взять строку и разобрать ее в массив символов Прокрутите массив и найдите первый «правильный символ» (в нашем примере это «a») Как только этот символ найден, проверьте следующий символ, продолжайте проверять каждый символ на соответствие, пока не будет найдено искомое значение. Если символ не совпадает, выйдите из итерации массива и перейдите к следующему слову.

...