【问题标题】:AutoCompleteTextView not completing words inside parenthesesAutoCompleteTextView 没有完成括号内的单词
【发布时间】:2015-10-03 18:33:01
【问题描述】:

我已经实现AutoCompleteTextView如下:

MainActivity.java

...
    public static String[] myData=new String[]{"Africa (AF)","America (AFM)","Apple (AMP)"};
    text=(AutoCompleteTextView)v.findViewById(R.id.first_state);
    ArrayAdapter adapter = new ArrayAdapter(getActivity(),R.layout.autocompletetextview_row,R.id.textViewItem,myData);

    text.setAdapter(adapter);
    text.setThreshold(1);
    text.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view, int position, long rowId) {

            selected_station = (String)parent.getItemAtPosition(position);
            //TODO Do something with the selected text
        }
    });

AutoCompleteTextView的布局中:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#FFFFFF"
    android:padding="10dp" >
    <TextView
        android:id="@+id/textViewItem"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:text="Item name here..."
        android:textColor="#000000"
        android:textSize="20sp" />
 </RelativeLayout>

当我键入“af..”时,它显示 非洲 (AF) 可供选择,但不显示 美国 (AFM)

数据只是示例数据。并不是说我只使用AutoCompleteTextView 来处理 3 个项目。

编辑:当我删除括号时,它可以正常工作。但我需要保留括号以备将来使用。

【问题讨论】:

  • 查看您的编辑后,我将删除我的答案:)。

标签: android android-arrayadapter autocompletetextview


【解决方案1】:

@BNK 提供的答案是正确的。但是,我想提供一个类似的解决方案,它不需要整个 ArrayAdapter 类文件。相反,我们将只扩展该类并覆盖其仅有的 2 个方法:getView()getFilter()。所以,定义你的 AutoSuggestAdapter 类:

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

例如在 XML 中定义自动完成视图:

       <AutoCompleteTextView
        android:id="@+id/autoComplete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="Enter some text ..."/>

并使用它:

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

【讨论】:

  • 最好使用 addAll 而不是在 foreach 中添加每个项目
  • @madim,addAll() 需要 API>=11。因此我更喜欢使用 add()
  • 我也有同样的问题,谁能看看我的question
  • 您的解决方案有效但很棘手,因为您没有公开这样一个事实,即由于 tempItems 仅在初始化时更新,过滤器不会显示对适配器集合的修改而不是在任何集合修改函数(添加、清除、插入等)中。
  • 我正在尝试使用您的解决方案,但在 publishResults 中调用 clear() 时出现 UnsupportedOperationException。有什么想法吗?
【解决方案2】:

ArrayAdapterfilterdefault 实现是搜索单词的开头(以空格分隔),我的意思是它使用 startsWith。您需要实现一个ArrayFilter,它使用containsstartsWith

您的问题将通过以下步骤解决:

  • here下载ArrayAdapter.java文件
  • 将该文件添加到项目中(例如,您可以通过将文件重命名为 CustomArrayAdapter.java 来重构)。
  • 在文件中,您将找到一个私有类ArrayFilter。然后,添加valueText.contains(prefixString)words[k].contains(prefixString) 如下:

                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;
                        }
                    }
                }
    
  • 为您的AutoCompleteTextView 使用自定义的ArrayAdapter

这是结果截图:

希望这会有所帮助!

【讨论】:

  • 其实如果我们使用“contains”,“startsWith”就已经是多余的了。
  • @SaQada 你是对的,但是,我保留了原始代码:)
  • 得到很多很多红线:/
  • 我也有同样的问题,谁能看看我的question
  • 我不明白为什么这个答案被批准并且得到了最多的支持!这不应该是正确的答案。下载系统适配器的原始源文件并手动编辑私有方法是非常糟糕的做法!你应该重写一些公共方法或者有你的自定义适配器,但肯定不是这样!
【解决方案3】:

要补充@Ayaz Alifov 的答案并纠正@Aballano 提出的问题, 这是一个更完整的带有 kotlin 代码的 AutoSuggestAdapter:


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

它应该适用于字符串或任何其他原始类型(或具有有效 toString 表示的对象/类)。它还允许您指定一个自定义函数来处理您想要使用非标准布局(不仅仅是 TextView)的自定义对象。它传递顶级视图容器和您要在下拉列表中表示的项目。

【讨论】:

    【解决方案4】:

    只需通过autoCompleteTextView.showDropDown() 手动显示下拉列表即可。

    例如:

    autoCompleteTextView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
    
            acSrcCity.showDropDown();
    
            return false;
        }
    });
    

    【讨论】:

      【解决方案5】:

      在您的情况下,您可以使用String.contains 而不是String.startsWith

      看到这个问题: custom-autocompletetextview-behavior

      【讨论】:

        【解决方案6】:

        如果你想添加数据

        String[] arr=new String[100];

        那就错了。 您可以执行与 ArrayList 形式相同的工作,但请记住,您永远不会在此处放置 Getter/Setter 类。只需简单地声明它。请参阅此示例。

        在主分区中声明:

           ArrayList<String>arr=new ArrayList<>();
        

        然后以这种方式初始化它:

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

        我希望这对你有用。

        【讨论】:

          猜你喜欢
          • 2014-10-30
          • 2023-04-07
          • 1970-01-01
          • 2022-06-29
          • 1970-01-01
          • 2012-10-13
          • 1970-01-01
          • 2011-03-25
          • 1970-01-01
          相关资源
          最近更新 更多