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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 08:54:08