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

Flutter搜索栏键盘弹出闪退问题:TextField空间适配求助

解决底部搜索栏键盘弹出后立即关闭的UI适配问题

我在实现类似YouTube的搜索栏并将其放置在屏幕底部附近时遇到问题:点击搜索栏后键盘弹出,但因空间不足立刻关闭,需要解决该UI适配问题。

问题代码

class YouTubeSearchBar extends GetView<YouTubeSearchBarController> {
  YouTubeSearchBarController youTubeSearchBarController;

  List<String> Suggestions;
  final String? hintText;
  final Color? textColor;
  final TextStyle? hintStyle;

  YouTubeSearchBar({
    super.key,
    required this.youTubeSearchBarController,
    required this.Suggestions,
    this.hintText,
    this.textColor,
    this.hintStyle,
  });

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Padding(
        padding: const EdgeInsets.all(5.0),
        child: Row(
          children: [
            Expanded(
              child: AutoCompleteTextField<String>(
                key: GlobalKey<AutoCompleteTextFieldState<String>>(),
                clearOnSubmit: false,
                suggestionsAmount: 50,
                style: TextStyle(color: textColor),
                suggestions: Suggestions,
                keyboardType: TextInputType.text,
                controller: controller.searchController,
                focusNode: controller.focusNode,
                decoration: InputDecoration(
                  hintText: hintText ?? '',
                  hintStyle: hintStyle,
                  filled: true,
                  fillColor: Color(0xFFFFF7EB),
                  enabledBorder: const OutlineInputBorder(
                      borderRadius: BorderRadius.all(Radius.circular(8.0)),
                      borderSide:
                          BorderSide(color: Color(0xFFF9A826), width: 1.0)),
                  border: const OutlineInputBorder(
                      borderRadius: BorderRadius.all(Radius.circular(8.0)),
                      borderSide:
                          BorderSide(color: Color(0xFFF9A826), width: 1.0)),
                  prefixIcon: Icon(Icons.search),
                ),
                itemBuilder: (context, suggestion) => ListTile(
                  title: Text(suggestion),
                  leading: SizedBox(
                    width: 15,
                    height: 15,
                    child: Obx(() => Checkbox(
                          value: true, // Replace with your logic
                          onChanged: (bool? value) {},
                        )),
                  ),
                ),
                itemFilter: (item, input) {
                  if (input.isBlank!) return true;
                  return item.toLowerCase().startsWith(input.toLowerCase());
                },
                itemSorter: (a, b) => a.compareTo(b),
                itemSubmitted: (item) {
                  if (item.isEmpty) {
                    // Handle when an empty text is submitted (show all suggestions)
                    print('Show all suggestions');
                  } else {
                    // Handle when a non-empty text is submitted
                    print('Selected item: $item');
                  }
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

解决方案

1. 调整页面根布局,确保整体可滚动

问题核心是搜索栏位于底部,键盘弹出时没有足够空间展示,导致焦点丢失、键盘关闭。需要让整个页面内容可滚动,同时确保Scaffold自动适配键盘高度:

Scaffold(
  resizeToAvoidBottomInset: true, // 必须开启,默认值为true,若被手动设为false需改回
  body: SingleChildScrollView(
    physics: const AlwaysScrollableScrollPhysics(), // 强制页面可滚动,即使内容不足
    child: Column(
      children: [
        // 页面其他内容组件
        // ...
        
        // 底部的搜索栏
        YouTubeSearchBar(
          youTubeSearchBarController: yourControllerInstance,
          Suggestions: yourSuggestionList,
          hintText: "搜索内容...",
        ),
      ],
    ),
  ),
);

2. 移除搜索栏内部的SingleChildScrollView

原组件内部的SingleChildScrollView是冗余的,会导致布局嵌套问题,直接移除即可:

class YouTubeSearchBar extends GetView<YouTubeSearchBarController> {
  final YouTubeSearchBarController youTubeSearchBarController;
  final List<String> Suggestions;
  final String? hintText;
  final Color? textColor;
  final TextStyle? hintStyle;

  YouTubeSearchBar({
    super.key,
    required this.youTubeSearchBarController,
    required this.Suggestions,
    this.hintText,
    this.textColor,
    this.hintStyle,
  });

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(5.0),
      child: Row(
        children: [
          Expanded(
            child: AutoCompleteTextField<String>(
              key: GlobalKey<AutoCompleteTextFieldState<String>>(),
              clearOnSubmit: false,
              suggestionsAmount: 50,
              style: TextStyle(color: textColor),
              suggestions: Suggestions,
              keyboardType: TextInputType.text,
              controller: controller.searchController,
              focusNode: controller.focusNode,
              decoration: InputDecoration(
                hintText: hintText ?? '',
                hintStyle: hintStyle,
                filled: true,
                fillColor: const Color(0xFFFFF7EB),
                enabledBorder: const OutlineInputBorder(
                    borderRadius: BorderRadius.all(Radius.circular(8.0)),
                    borderSide:
                        BorderSide(color: Color(0xFFF9A826), width: 1.0)),
                border: const OutlineInputBorder(
                    borderRadius: BorderRadius.all(Radius.circular(8.0)),
                    borderSide:
                        BorderSide(color: Color(0xFFF9A826), width: 1.0)),
                prefixIcon: const Icon(Icons.search),
              ),
              itemBuilder: (context, suggestion) => ListTile(
                title: Text(suggestion),
                leading: SizedBox(
                  width: 15,
                  height: 15,
                  child: Obx(() => Checkbox(
                        value: true, // 替换为实际业务逻辑
                        onChanged: (bool? value) {},
                      )),
                ),
              ),
              itemFilter: (item, input) {
                if (input.isBlank!) return true;
                return item.toLowerCase().startsWith(input.toLowerCase());
              },
              itemSorter: (a, b) => a.compareTo(b),
              itemSubmitted: (item) {
                if (item.isEmpty) {
                  print('显示所有建议');
                } else {
                  print('选中项: $item');
                }
              },
            ),
          ),
        ],
      ),
    );
  }
}

3. 可选:动态调整搜索栏位置(针对极端场景)

如果仍存在键盘遮挡问题,可以借助键盘监听包flutter_keyboard_visibility动态调整布局:

  1. 添加依赖到pubspec.yaml:
dependencies:
  flutter_keyboard_visibility: ^6.0.0
  1. 在页面中使用键盘监听:
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';

class YourPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return KeyboardVisibilityBuilder(
      builder: (context, isKeyboardVisible) {
        return Scaffold(
          body: SingleChildScrollView(
            child: Column(
              children: [
                // 其他内容
                // ...
                
                // 根据键盘状态动态添加间距
                SizedBox(height: isKeyboardVisible ? 160 : 0),
                
                YouTubeSearchBar(
                  youTubeSearchBarController: yourControllerInstance,
                  Suggestions: yourSuggestionList,
                  hintText: "搜索内容...",
                ),
              ],
            ),
          ),
        );
      },
    );
  }
}

内容的提问来源于stack exchange,提问作者Vishal Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 05:05:56