AutoCompleteTextView not completing words inside parentheses

后端 未结 6 378
灰色年华
灰色年华 2020-12-03 00:11

I have implemented AutoCompleteTextView as follows:

MainActivity.java

...
    public static String[] myData=new String[         


        
相关标签:
6条回答
  • 2020-12-03 00:35

    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.

    0 讨论(0)
  • 2020-12-03 00:47

    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:

    • Download the ArrayAdapter.java file from here
    • Add that file into the project (you can refactor by renaming file to CustomArrayAdapter.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!

    0 讨论(0)
  • 2020-12-03 00:47

    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.

    0 讨论(0)
  • 2020-12-03 00:51

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

    0 讨论(0)
  • 2020-12-03 01:00

    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;
        }
    });
    
    0 讨论(0)
  • 2020-12-03 01:01

    In your case, you could use String.contains instead of String.startsWith.

    See this question: custom-autocompletetextview-behavior

    0 讨论(0)
提交回复
热议问题