Custom AutoCompleteTextView behavior

偶尔善良 提交于 2019-11-29 10:10:00

You would need to write a custom Filter class and implement the performFiltering method yourself. This method takes a CharSequence argument, which you can use to perform whatever String operations you need in order to generate a list of matches from your dataset (in your case, you could use String.contains instead of String.startsWith). The performFiltering function is not run on the UI thread.

You then return your list of matches as a FilterResults object, which contains an Object values (your list of matches, probably an ArrayList) and an int count which is the size of your list of matches.

Finally, implement the publishResults callback method, which returns once the worker thread has generated the list of matches, allowing you to call notifyDataSetChanged on your AutoCompleteTextView's adapter so that it can display the results.

Old question, but still relevant. Following the guidance of a few other questions implemented a custom adapter using filterable. I made a simple generic adapter that searches with contains. Quick notes on it:

I'm using butterknife, but easy to do the viewHolder with findviewbyid.

The layout R.layout.list_item_simple is a simple layout with the textview R.id.text_view_simple.

The object needs a toString that will be compared.

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);
        }
    }
}
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;
}

}

My advice would be to parse the string into a character array. Then iterate each character until the string is found.

For example lets say your search wanted to return all words with "ate" in them and the word list was...

state trait berate late

Your algorithm should go something like this

Take the string and parse it into a character array Loop through the array and find the first "correct character" (in our example its 'a') Once that character is found check the next character, keep checking each character for a match until the value being searched for is complete. If the character is not a match exit the array iteration and go to the next word.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!