You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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"/>

问题原因

  1. 调用时机过早:执行高度计算时,过滤后的数据集尚未同步到UI,下拉列表也未完成初始化,导致计算结果无效。
  2. 测量容器错误:用TextInputLayout作为父容器测量Item高度,与下拉列表实际的布局环境不符,得到的Item高度不准确。
  3. 计算逻辑冗余:重复叠加了垂直内边距,每个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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 10:50:38