AutoCompleteTextView下拉列表高度无法随过滤结果自适应求助
AutoCompleteTextView下拉列表高度无法随过滤结果自适应的解决方法
问题描述
给AutoCompleteTextView绑定自定义ArrayAdapter后,用户输入过滤内容时,下拉列表高度始终固定——比如匹配结果为3条或1条时,下拉框尺寸完全一致。已尝试动态计算高度的方法(见下方代码),并在adapter.notifyDataSetChanged()后调用,但无效果;XML布局中也已设置android:dropDownHeight="wrap_content"。
现有代码
Kotlin动态计算高度方法
private fun adjustListHeight() { // After calling adapter.notifyDataSetChanged() val filteredItemCount = autoCompleteAdapter.getFilteredItemCount() // Calculate the height of the dropdown list based on the number of items and the height of the first item val firstItemView = autoCompleteAdapter.getView(0, null, binding.descriptionTextInputLayout) val measureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED) firstItemView.measure(measureSpec, measureSpec) val itemHeight = firstItemView.measuredHeight val verticalPadding = firstItemView.paddingTop + firstItemView.paddingBottom val dropdownHeight = if (filteredItemCount > 0) { // Calculate the total height of the dropdown list based on the number of items and item height val totalHeight = (filteredItemCount * itemHeight) + (2 * verticalPadding) totalHeight } else { // Default height when no items are available ViewGroup.LayoutParams.WRAP_CONTENT } // Set the calculated height to the AutoCompleteTextView's dropdown list binding.descriptionEditText.dropDownHeight = dropdownHeight }
XML布局
<AutoCompleteTextView android:id="@+id/descriptionEditText" style="@style/TextAppearance.FontPath.Regular" android:layout_width="match_parent" android:layout_height="wrap_content" android:cursorVisible="true" android:ellipsize="end" android:inputType="textCapCharacters" android:maxLines="1" android:dropDownHeight="wrap_content" android:paddingTop="8dp" android:textColor="@color/global_gray_dark_text" android:textCursorDrawable="@drawable/drawable_cursor_color" android:textSize="20sp" android:theme="@style/customCursor" tools:text="69774839234234234234234234234" tools:drawableEnd="@drawable/ic_contacts_2"/>
问题原因
- 调用时机过早:执行高度计算时,过滤后的数据集尚未同步到UI,下拉列表也未完成初始化,导致计算结果无效。
- 测量容器错误:用
TextInputLayout作为父容器测量Item高度,与下拉列表实际的布局环境不符,得到的Item高度不准确。 - 计算逻辑冗余:重复叠加了垂直内边距,每个Item本身已包含上下内边距,无需额外添加。
解决方法
方法一:修正测量逻辑与调用时机
调整adjustListHeight方法,确保在UI线程异步执行,并使用模拟下拉环境的容器测量Item高度:
private fun adjustListHeight() { val filteredCount = autoCompleteAdapter.getFilteredItemCount() if (filteredCount == 0) { binding.descriptionEditText.dropDownHeight = ViewGroup.LayoutParams.WRAP_CONTENT return } // 用临时LinearLayout模拟下拉列表的布局容器 val tempParent = LinearLayout(context) tempParent.layoutParams = ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT ) val firstItem = autoCompleteAdapter.getView(0, null, tempParent) // 按下拉列表实际宽度测量Item高度 val widthSpec = MeasureSpec.makeMeasureSpec( binding.descriptionEditText.width, MeasureSpec.EXACTLY ) val heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED) firstItem.measure(widthSpec, heightSpec) val itemHeight = firstItem.measuredHeight // 总高度=Item高度×数量(Item自身已包含内边距,无需额外计算) val totalHeight = filteredCount * itemHeight // 异步设置高度并强制刷新下拉列表 binding.descriptionEditText.post { binding.descriptionEditText.dropDownHeight = totalHeight binding.descriptionEditText.showDropDown() } }
在Adapter的过滤完成回调中触发高度调整:
override fun getFilter(): Filter { return object : Filter() { override fun performFiltering(constraint: CharSequence?): FilterResults { // 自定义过滤逻辑 val filteredList = // 你的过滤结果 val results = FilterResults() results.values = filteredList results.count = filteredList.size return results } override fun publishResults(constraint: CharSequence?, results: FilterResults?) { filteredList = results?.values as? List<YourDataModel> ?: emptyList() notifyDataSetChanged() // 过滤完成后调用高度调整 adjustListHeight() } } }
方法二:简易触发方式(无需修改Adapter)
在下拉列表即将显示时延迟触发高度计算:
binding.descriptionEditText.setOnTouchListener { _, event -> if (event.action == MotionEvent.ACTION_UP) { binding.descriptionEditText.postDelayed({ adjustListHeight() }, 100) } false }
方法三:强制重置布局(快速修复)
若wrap_content未生效,可在过滤完成后强制重置下拉高度:
binding.descriptionEditText.dropDownHeight = ViewGroup.LayoutParams.WRAP_CONTENT binding.descriptionEditText.requestLayout()
内容的提问来源于stack exchange,提问作者Pointyhat
相关产品推荐
相关产品推荐

