Android带搜索下拉菜单问题:限制选择与模糊搜索实现
用AutocompleteTextView实现限制输入+包含式搜索
完全可以通过自定义适配器和添加监听来实现你需要的两个功能,下面是具体方案:
一、实现包含式搜索(解决需求b)
默认的ArrayAdapter采用前缀匹配,我们需要自定义适配器并重写Filter来实现包含式过滤:
class ContainsFilterArrayAdapter(context: Context, resource: Int, objects: List<String>) : ArrayAdapter<String>(context, resource, objects) { private val originalList = ArrayList(objects) override fun getFilter(): Filter { return object : Filter() { override fun performFiltering(constraint: CharSequence?): FilterResults { val results = FilterResults() val filteredList = ArrayList<String>() constraint?.let { query -> val lowerCaseQuery = query.toString().lowercase() originalList.forEach { item -> // 忽略大小写的包含匹配 if (item.lowercase().contains(lowerCaseQuery)) { filteredList.add(item) } } } ?: run { filteredList.addAll(originalList) } results.values = filteredList results.count = filteredList.size return results } override fun publishResults(constraint: CharSequence?, results: FilterResults?) { clear() results?.values?.let { values -> addAll(values as Collection<String>) } notifyDataSetChanged() } } } }
二、禁止自定义输入(解决需求a)
不能用android:inputType="none"(会丢失搜索功能),而是通过监听输入和焦点变化,确保最终只有预定义选项能保留:
在Fragment中设置适配器并添加监听:
val countries = arrayListOf("Czech Republic","Slovakia", "Poland", "Germany","Austria") val countriesAdapter = ContainsFilterArrayAdapter(requireContext(), R.layout.support_simple_spinner_dropdown_item, countries) binding?.actCountries?.apply { setAdapter(countriesAdapter) // 记录用户选中的有效选项 var selectedCountry: String? = null // 选中项时保存当前值 onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -> selectedCountry = countriesAdapter.getItem(position) } // 失去焦点时验证文本有效性,无效则重置 onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus -> if (!hasFocus) { val currentText = text.toString() if (currentText.isNotEmpty() && !countries.contains(currentText)) { // 重置为上次选中的内容,也可以直接清空 setText(selectedCountry ?: "", false) } } } // 软键盘完成键触发时验证 setOnEditorActionListener { _, actionId, _ -> if (actionId == EditorInfo.IME_ACTION_DONE) { val currentText = text.toString() if (currentText.isNotEmpty() && !countries.contains(currentText)) { setText(selectedCountry ?: "", false) // 隐藏软键盘 val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.hideSoftInputFromWindow(windowToken, 0) } true } else { false } } }
三、XML布局保持不变
你的原有布局无需修改,继续使用TextInputLayout搭配AutocompleteTextView即可:
<com.google.android.material.textfield.TextInputLayout style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Country"> <AutoCompleteTextView android:id="@+id/actCountries" android:layout_width="match_parent" android:layout_height="wrap_content"> </AutoCompleteTextView> </com.google.android.material.textfield.TextInputLayout>
效果说明
- 用户可以输入内容进行搜索,输入的字符会在所有预定义选项中进行包含式匹配(比如输入"land"会匹配到"Poland")
- 输入的内容如果不在预定义列表中,失去焦点或按下完成键时会自动重置为上次选中的内容(或清空),确保最终只能选择预定义选项
内容的提问来源于stack exchange,提问作者OndraVojta
相关产品推荐
相关产品推荐

