Flutter RawAutocomplete建议列表被软键盘遮挡如何配置optionsViewBuilder
Flutter RawAutocomplete 选项列表被软键盘遮挡解决方案
核心逻辑是动态计算输入框上下的可用空间,自动调整选项列表的展示位置,当下方空间(扣除软键盘高度)不足以放下列表时,将列表展示在输入框上方,同时限制列表最大高度避免超出屏幕。
具体修改步骤
1. 保留原有全局key
你代码中已经定义了_autocompleteKey用于定位输入框组件,无需额外新增变量。
2. 替换optionsViewBuilder逻辑
将原有optionsViewBuilder替换为以下代码:
optionsViewBuilder: (BuildContext context, AutocompleteOnSelected<String> onSelected, Iterable<String> options) { // 组件未渲染完成时返回空占位 if (_autocompleteKey.currentContext == null) return const SizedBox.shrink(); // 获取输入框的位置和尺寸信息 final RenderBox renderBox = _autocompleteKey.currentContext!.findRenderObject() as RenderBox; final fieldOffset = renderBox.localToGlobal(Offset.zero); final fieldHeight = renderBox.size.height; final fieldWidth = renderBox.size.width; final fieldBottomY = fieldOffset.dy + fieldHeight; // 获取屏幕参数和软键盘高度 final screenHeight = MediaQuery.of(context).size.height; final keyboardHeight = MediaQuery.of(context).viewInsets.bottom; // 输入框下方可用高度 = 屏幕底部 - 输入框底部 - 软键盘高度 final availableHeightBelow = screenHeight - fieldBottomY - keyboardHeight; // 输入框上方可用高度 = 输入框顶部距离(避开状态栏) final availableHeightAbove = fieldOffset.dy - MediaQuery.of(context).padding.top; // 计算选项列表的预期最大高度,最多展示5个选项,每个高度按56dp算 final expectedMaxHeight = min(options.length * 56.0, 280.0); // 最终列表的最大高度,取上下可用空间的最大值,避免超出屏幕 final finalMaxHeight = min(expectedMaxHeight, max(availableHeightAbove, availableHeightBelow)); // 判断是否要展示在输入框上方 final showAbove = availableHeightBelow < expectedMaxHeight && availableHeightAbove > availableHeightBelow; return Padding( // 调整偏移量:在下方就偏移输入框高度的距离,在上方就偏移负的列表高度 padding: EdgeInsets.only( top: showAbove ? 0 : fieldHeight, bottom: showAbove ? fieldHeight : 0, ), child: Align( alignment: showAbove ? Alignment.bottomLeft : Alignment.topLeft, child: Material( elevation: 4.0, // 列表宽度和输入框保持一致 width: fieldWidth, child: ConstrainedBox( constraints: BoxConstraints(maxHeight: finalMaxHeight), child: ListView.builder( padding: EdgeInsets.zero, shrinkWrap: true, itemCount: options.length, itemBuilder: (context, index) { final option = options.elementAt(index); return GestureDetector( onTap: () => onSelected(option), child: ListTile(title: Text(option)), ); }, ), ), ), ), ); },
补充说明
- 注意代码中使用了dart:math库的min/max方法,需要在文件顶部引入
import 'dart:math'; - 代码中自动适配软键盘高度,软键盘弹出时MediaQuery会触发重绘,列表位置会自动调整
- 列表默认限制最大高度为280dp(5个ListTile的高度),可根据业务需求调整
- 自动优先选择上下方空间更大的一侧展示列表,上下空间都不足时自动限制列表高度并支持滚动
内容的提问来源于stack exchange,提问作者Ashish Khurange
相关产品推荐
相关产品推荐

