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动态调整布局:
- 添加依赖到
pubspec.yaml:
dependencies: flutter_keyboard_visibility: ^6.0.0
- 在页面中使用键盘监听:
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
相关产品推荐
相关产品推荐

