I have implemented AutoCompleteTextView
as follows:
MainActivity.java
...
public static String[] myData=new String[
To add to the answer by @Ayaz Alifov and remediate the concerns offered by @Aballano, here is a more complete AutoSuggestAdapter with kotlin code:
import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.Filter
import android.widget.TextView
class AutoSuggestAdapter<T : Any>(context: Context, private val resource: Int, items : List<T> = ArrayList()) :
ArrayAdapter<T>(context, resource, items) {
private val items : ArrayList<T> = ArrayList()
private val suggestions : ArrayList<T> = ArrayList()
var customLayoutHandler : ((View, T) -> Unit)? = null
companion object {
private const val TAG = "AutoSuggestAdapter"
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
lateinit var v : View
v = if(convertView == null){
val inflater : LayoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
inflater.inflate(resource, parent, false)
} else convertView
val item : T = suggestions[position]
if(v is TextView) v.text = item.toString()
else customLayoutHandler?.invoke(v,item)
return v
}
override fun getFilter() : Filter = itemFilter
override fun add(item: T?) {
if(item != null) super.add(item)
if(item != null && !items.contains(item)) items.add(item)
}
override fun addAll(vararg items: T) {
super.addAll(*items)
this.items.addAll(items)
}
override fun addAll(collection: MutableCollection<out T>) {
super.addAll(collection)
this.items.addAll(collection)
}
fun clearItems(){
items.clear()
}
inner class ItemFilter() : Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults {
if(constraint != null){
suggestions.clear()
items.forEach { item ->
if(item.toString().toLowerCase().contains(constraint.toString().toLowerCase())) suggestions.add(item)
}
val fResults : FilterResults = FilterResults()
fResults.values = suggestions
fResults.count = suggestions.size
return fResults
}
return FilterResults()
}
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
if(results != null && results.count > 0){
var filterList : ArrayList<T> = results?.values as ArrayList<T>
clear()
filterList.forEach { item -> add(item) }
notifyDataSetChanged()
}
}
override fun convertResultToString(resultValue: Any?): CharSequence {
return resultValue?.toString() ?: ""
}
}
private val itemFilter : ItemFilter = ItemFilter()
}
It should work out of the box for Strings or any other primitive type (or objects/classes where you have a valid toString representation). It also allows for you to specify a custom function to handle custom objects where you want to use a non-standard layout (other than just a TextView). It passes the top level view container and the item you want to represent in the dropdown.
The default implementation of the filter for ArrayAdapter
is searching the beginning of words (separated by space), I mean it uses startsWith
. You will need to implement an ArrayFilter
which uses contains
together with startsWith
.
Your issue will be solved by the following steps:
ArrayAdapter.java
file from hereCustomArrayAdapter.java
, for example).In the file, you will find a private class ArrayFilter
. Then, add valueText.contains(prefixString)
and words[k].contains(prefixString)
as the following:
if (valueText.startsWith(prefixString) || valueText.contains(prefixString)) {
newValues.add(value);
} else {
final String[] words = valueText.split(" ");
final int wordCount = words.length;
// Start at index 0, in case valueText starts with space(s)
for (int k = 0; k < wordCount; k++) {
if (words[k].startsWith(prefixString) || words[k].contains(prefixString)) {
newValues.add(value);
break;
}
}
}
Use that customized ArrayAdapter
for your AutoCompleteTextView
And here is the result screenshot:
Hope this helps!
if you are wanna add the data in
String[] arr=new String[100];
then its wrong. You can do the same work as in form of ArrayList but remember you will never put here a Getter/Setter class. Just simply declare it. See this example.
Declare in main partition:
ArrayList<String>arr=new ArrayList<>();
and then initilize it in this way:
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject1 = (JSONObject) jsonArray.get(i);
String imei = jsonObject1.getString("imei");
String name = jsonObject1.getString("name");
String my_pic = jsonObject1.getString("my_pic");
String email = jsonObject1.getString("email");
arr.add(name);
}
adapter= new ArrayAdapter<>
(this, android.R.layout.select_dialog_item, arr);
autoCompleteText.setThreshold(1);//will start working from first character
autoCompleteText.setAdapter(adapter);//setting the adapter data into the AutoCompleteTextView
autoCompleteText.setTextColor(Color.RED);
}
I hope this will work for you.
An answer, provided by @BNK, is correct. However, I would like to give a similar solution, which doesn't require the whole ArrayAdapter
class file. Instead, we will just extend that class and override its only 2 methods: getView()
and getFilter()
. So, define your AutoSuggestAdapter class:
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class AutoSuggestAdapter extends ArrayAdapter
{
private Context context;
private int resource;
private List<String> items;
private List<String> tempItems;
private List<String> suggestions;
public AutoSuggestAdapter(Context context, int resource, List<String> items)
{
super(context, resource, 0, items);
this.context = context;
this.resource = resource;
this.items = items;
tempItems = new ArrayList<String>(items);
suggestions = new ArrayList<String>();
}
@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(resource, parent, false);
}
String item = items.get(position);
if (item != null && view instanceof TextView)
{
((TextView) view).setText(item);
}
return view;
}
@Override
public Filter getFilter()
{
return nameFilter;
}
Filter nameFilter = new Filter()
{
@Override
public CharSequence convertResultToString(Object resultValue)
{
String str = (String) resultValue;
return str;
}
@Override
protected FilterResults performFiltering(CharSequence constraint)
{
if (constraint != null)
{
suggestions.clear();
for (String names : tempItems)
{
if (names.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<String> filterList = (ArrayList<String>) results.values;
if (results != null && results.count > 0)
{
clear();
for (String item : filterList)
{
add(item);
notifyDataSetChanged();
}
}
}
};
}
Define auto complete view in XML for example:
<AutoCompleteTextView
android:id="@+id/autoComplete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Enter some text ..."/>
And use it:
AutoCompleteTextView autoComplete = (AutoCompleteTextView) findViewById(R.id.autoComplete);
List <String> stringList = new ArrayList<String>();
stringList.add("Black");
stringList.add("White");
stringList.add("Yellow");
stringList.add("Green");
stringList.add("Blue");
stringList.add("Brown");
stringList.add("Orange");
stringList.add("Pink");
stringList.add("Violet");
stringList.add("Cyan");
stringList.add("LightBlue");
AutoSuggestAdapter adapter = new AutoSuggestAdapter(this, android.R.layout.simple_list_item_1, stringList);
autoComplete.setAdapter(adapter);
// specify the minimum type of characters before drop-down list is shown
autoComplete.setThreshold(1);
Just manually show the drop-down via autoCompleteTextView.showDropDown()
everywhere you want.
For example:
autoCompleteTextView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
acSrcCity.showDropDown();
return false;
}
});
In your case, you could use String.contains
instead of String.startsWith
.
See this question: custom-autocompletetextview-behavior