Change AutoCompleteTextView filter from "startsWith" to "Contains"?

I want to change the default filtering in AutoCompleteTextView . Filtering by default finds all lines that begin with a given token. My project requires filtering to find all rows containing a given token.

Is it possible?

+12
source share
5 answers

I found a solution for this, thanks google and search for two days. As @ torque203 suggested, I implemented my own custom adapter. First, define a new XML file for the user element in the adapter:

autocomplete_item.xml

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="Medium Text" android:paddingLeft="8dp" android:paddingRight="8dp" android:paddingTop="16dp" android:paddingBottom="16dp" android:id="@+id/lbl_name" /> </RelativeLayout> 

Create a new class for your names:

Names

 public class Names { public String name; } 

NamesAdapter

 public class NamesAdapter extends ArrayAdapter<Names> { Context context; int resource, textViewResourceId; List<Names> items, tempItems, suggestions; public NamesAdapter(Context context, int resource, int textViewResourceId, List<Names> items) { super(context, resource, textViewResourceId, items); this.context = context; this.resource = resource; this.textViewResourceId = textViewResourceId; this.items = items; tempItems = new ArrayList<Names>(items); // this makes the difference. suggestions = new ArrayList<Names>(); } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = convertView; if (convertView == null) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(R.layout.autocomplete_item, parent, false); } Names names = items.get(position); if (names != null) { TextView lblName = (TextView) view.findViewById(R.id.lbl_name); if (lblName != null) lblName.setText(names.name); } return view; } @Override public Filter getFilter() { return nameFilter; } /** * Custom Filter implementation for custom suggestions we provide. */ Filter nameFilter = new Filter() { @Override public CharSequence convertResultToString(Object resultValue) { String str = ((Names) resultValue).name; return str; } @Override protected FilterResults performFiltering(CharSequence constraint) { if (constraint != null) { suggestions.clear(); for (Names names : tempItems) { if (names.name.toLowerCase().contains(constraint.toString().toLowerCase())) { suggestions.add(names); } } FilterResults filterResults = new FilterResults(); filterResults.values = suggestions; filterResults.count = suggestions.size(); return filterResults; } else { return new FilterResults(); } } @Override protected void publishResults(CharSequence constraint, FilterResults results) { List<Names> filterList = (ArrayList<Names>) results.values; if (results != null && results.count > 0) { clear(); for (Names names : filterList) { add(names); notifyDataSetChanged(); } } } }; } 

SearchActivity (or your main action)

 .... List<Names> namesList = //your names list; NamesAdapter namesAdapter = new NamesAdapter( SearchActivity.this, R.layout.activity_search, R.id.lbl_name, namesList ); //set adapter into listStudent autoCompleteTextView.setAdapter(namesAdapter); autoCompleteTextView.showDropDown(); ... 
+17
source

Yes it is possible.

First way:

You should create a custom adapter that implements ListAdapter and Filterable .

Filter , than can implement the logic of the filter "contains"

And you install this adapter as an adapter for your autocomplete.

The second way:

If you are already using an ArrayAdapter . You can simply override the getFilter () method.

0
source

Just to expand on Caffe Latte's nice answer:

1) autoCompleteTextView.showDropDown(); not required.

2) To extract the input object, you can use:

 //retrieve the input in the autoCompleteTextView autoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() { //parent The AdapterView where the click happened. //view The view within the AdapterView that was clicked (this will be a view provided by the adapter) //position The position of the view in the adapter //id The row id of the item that was clicked. public void onItemClick(AdapterView<?> parent, View view, int position, long rowId) { String selection =parent.getItemAtPosition(position).toString(); Toast.makeText(parent.getContext(),"" + selection,Toast.LENGTH_SHORT).show(); } }); 

An object obtained from the parent must have the toString () method.

0
source

//try it

 autoCompleteText.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View arg1, int position, long arg3) { YourCustomModel YourFilterdSelectedModel = (YourCustomModel) adapterView.getItemAtPosition(position); autoCompleteText.setText(str); } }); 

£ It worked for me

0
source

Here is a simpler version of Kotlin posted by @Caffe Latte.

You don't need a custom layout file, just use the standard android.R.layout.simple_list_item_1 .

Specify any class for this adapter, including regular strings. It just uses toString() to determine the text to display.

 import android.content.Context import android.widget.ArrayAdapter import android.widget.Filter import androidx.annotation.IdRes import androidx.annotation.LayoutRes import java.util.* class AutoCompleteAdapter( context: Context, @LayoutRes resource: Int, @IdRes textViewResourceId: Int = 0, internal var items: List<Any> = listOf() ) : ArrayAdapter<Any>(context, resource, textViewResourceId, items) { internal var tempItems: MutableList<Any> = mutableListOf() internal var suggestions: MutableList<Any> = mutableListOf() /** * Custom Filter implementation for custom suggestions we provide. */ private var filter: Filter = object : Filter() { override fun performFiltering(constraint: CharSequence?): FilterResults { return if (constraint != null) { suggestions.clear() tempItems.forEach { if (it.toString().toLowerCase(Locale.getDefault()).contains(constraint.toString().toLowerCase(Locale.getDefault()))) { suggestions.add(it) } } val filterResults = FilterResults() filterResults.values = suggestions filterResults.count = suggestions.size filterResults } else { FilterResults() } } override fun publishResults(constraint: CharSequence?, results: FilterResults) { val filterList = results.values as? List<Any> if (results.count > 0) { clear() filterList?.forEach { add(it) }.also { notifyDataSetChanged() } } } } init { tempItems = items.toMutableList() suggestions = ArrayList() } override fun getFilter(): Filter { return filter } } 
0
source

Source: https://habr.com/ru/post/1241719/


All Articles