搜索框与抽屉冲突问题
							parent
							
								
									fa4b765565
								
							
						
					
					
						commit
						e7fbd5e12c
					
				|  | @ -184,6 +184,7 @@ class _DepartmentPickerState extends State<DepartmentPicker> { | ||||||
|                       controller: _searchController, |                       controller: _searchController, | ||||||
|                       isShowSearchButton: false, |                       isShowSearchButton: false, | ||||||
|                       onSearch: (keyboard) { |                       onSearch: (keyboard) { | ||||||
|  | 
 | ||||||
|                       }, |                       }, | ||||||
|                     ), |                     ), | ||||||
|                   ), |                   ), | ||||||
|  |  | ||||||
|  | @ -1,43 +1,59 @@ | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| 
 | 
 | ||||||
| class SearchBarWidget extends StatelessWidget { | class SearchBarWidget extends StatefulWidget { | ||||||
|   final String hintText; |   final String hintText; | ||||||
|   final String buttonText; |   final String buttonText; | ||||||
|   final ValueChanged<String> onSearch; |   final ValueChanged<String> onSearch; | ||||||
|   final TextEditingController controller; // 改为必传参数 |   final TextEditingController controller; | ||||||
|   final bool autoFocus; |  | ||||||
|   final bool showResetButton; |   final bool showResetButton; | ||||||
|   final String resetButtonText; |   final String resetButtonText; | ||||||
|   final VoidCallback? onReset; |   final VoidCallback? onReset; | ||||||
|   final bool isClickableOnly; |   final bool isClickableOnly; | ||||||
|   final VoidCallback? onInputTap; |   final VoidCallback? onInputTap; | ||||||
|   final ValueChanged<String>? onTextChanged; // 新增文本变化回调 |   final ValueChanged<String>? onTextChanged; | ||||||
|   final bool isShowSearchButton; |   final bool isShowSearchButton; | ||||||
| 
 | 
 | ||||||
|   const SearchBarWidget({ |   const SearchBarWidget({ | ||||||
|     Key? key, |     Key? key, | ||||||
|     required this.onSearch, |     required this.onSearch, | ||||||
|     required this.controller, // 必须传入controller |     required this.controller, | ||||||
|     this.hintText = '请输入关键字', |     this.hintText = '请输入关键字', | ||||||
|     this.buttonText = '搜索', |     this.buttonText = '搜索', | ||||||
|     this.autoFocus = false, |  | ||||||
|     this.showResetButton = false, |     this.showResetButton = false, | ||||||
|     this.resetButtonText = '重置', |     this.resetButtonText = '重置', | ||||||
|     this.onReset, |     this.onReset, | ||||||
|     this.isClickableOnly = false, |     this.isClickableOnly = false, | ||||||
|     this.onInputTap, |     this.onInputTap, | ||||||
|     this.onTextChanged, // 可选文本变化监听 |     this.onTextChanged, | ||||||
|     this.isShowSearchButton = true, |     this.isShowSearchButton = true, | ||||||
|   }) : super(key: key); |   }) : super(key: key); | ||||||
| 
 | 
 | ||||||
|   // 公共方法:更新输入框内容(可在外部调用) |   @override | ||||||
|  |   _SearchBarWidgetState createState() => _SearchBarWidgetState(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class _SearchBarWidgetState extends State<SearchBarWidget> { | ||||||
|  |   late FocusNode _focusNode; | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   void initState() { | ||||||
|  |     super.initState(); | ||||||
|  |     _focusNode = FocusNode(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   void dispose() { | ||||||
|  |     _focusNode.dispose(); | ||||||
|  |     super.dispose(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /// 更新输入框内容(可在外部调用) | ||||||
|   void updateText(String newText) { |   void updateText(String newText) { | ||||||
|     controller.text = newText; |     widget.controller.text = newText; | ||||||
|     controller.selection = TextSelection.fromPosition( |     widget.controller.selection = TextSelection.fromPosition( | ||||||
|       TextPosition(offset: newText.length), |       TextPosition(offset: newText.length), | ||||||
|     ); |     ); | ||||||
|     // 可选:触发文本变化回调 |     widget.onTextChanged?.call(newText); | ||||||
|     onTextChanged?.call(newText); |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|  | @ -45,39 +61,38 @@ class SearchBarWidget extends StatelessWidget { | ||||||
|     return Row( |     return Row( | ||||||
|       children: [ |       children: [ | ||||||
|         Expanded( |         Expanded( | ||||||
|           child: GestureDetector( |           child: TextField( | ||||||
|             onTap: isClickableOnly ? onInputTap : null, |             focusNode: _focusNode, | ||||||
|             child: AbsorbPointer( |             controller: widget.controller, | ||||||
|               absorbing: isClickableOnly, |             readOnly: widget.isClickableOnly, | ||||||
|               child: TextField( |             autofocus: false, | ||||||
|                 controller: controller, |             style: const TextStyle(fontSize: 15), | ||||||
|                 autofocus: autoFocus, |             onChanged: widget.onTextChanged, | ||||||
|                 readOnly: isClickableOnly, |             onTap: () { | ||||||
|                 style: const TextStyle(fontSize: 15), |               if (widget.isClickableOnly) { | ||||||
|                 onChanged: onTextChanged, |                 // 可点击但不弹出键盘 | ||||||
|                 // 监听文本变化 |                 widget.onInputTap?.call(); | ||||||
|                 decoration: InputDecoration( |               } | ||||||
|                   filled: true, |             }, | ||||||
|                   fillColor: const Color(0xFFF5F5F5), |             decoration: InputDecoration( | ||||||
|                   prefixIcon: const Icon(Icons.search_rounded), |               filled: true, | ||||||
|                   hintText: hintText, |               fillColor: const Color(0xFFF5F5F5), | ||||||
|                   border: OutlineInputBorder( |               prefixIcon: const Icon(Icons.search_rounded), | ||||||
|                     borderRadius: BorderRadius.circular(5), |               hintText: widget.hintText, | ||||||
|                     borderSide: BorderSide.none, |               border: OutlineInputBorder( | ||||||
|                   ), |                 borderRadius: BorderRadius.circular(5), | ||||||
|                   isDense: true, |                 borderSide: BorderSide.none, | ||||||
|                   contentPadding: const EdgeInsets.symmetric(vertical: 8), |  | ||||||
|                 ), |  | ||||||
|                 onSubmitted: onSearch, |  | ||||||
|               ), |               ), | ||||||
|  |               isDense: true, | ||||||
|  |               contentPadding: const EdgeInsets.symmetric(vertical: 8), | ||||||
|             ), |             ), | ||||||
|  |             onSubmitted: widget.onSearch, | ||||||
|           ), |           ), | ||||||
|         ), |         ), | ||||||
|         const SizedBox(width: 10), |         const SizedBox(width: 10), | ||||||
|         if (isShowSearchButton) |         if (widget.isShowSearchButton) | ||||||
|           // 搜索按钮 |  | ||||||
|           ElevatedButton( |           ElevatedButton( | ||||||
|             onPressed: () => onSearch(controller.text.trim()), |             onPressed: () => widget.onSearch(widget.controller.text.trim()), | ||||||
|             style: ElevatedButton.styleFrom( |             style: ElevatedButton.styleFrom( | ||||||
|               backgroundColor: Colors.green, |               backgroundColor: Colors.green, | ||||||
|               padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8), |               padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8), | ||||||
|  | @ -88,17 +103,16 @@ class SearchBarWidget extends StatelessWidget { | ||||||
|               shadowColor: Colors.black45, |               shadowColor: Colors.black45, | ||||||
|             ), |             ), | ||||||
|             child: Text( |             child: Text( | ||||||
|               buttonText, |               widget.buttonText, | ||||||
|               style: const TextStyle(color: Colors.white, fontSize: 16), |               style: const TextStyle(color: Colors.white, fontSize: 16), | ||||||
|             ), |             ), | ||||||
|           ), |           ), | ||||||
|         // 重置按钮 |         if (widget.showResetButton) const SizedBox(width: 10), | ||||||
|         if (showResetButton) const SizedBox(width: 10), |         if (widget.showResetButton) | ||||||
|         if (showResetButton) |  | ||||||
|           ElevatedButton( |           ElevatedButton( | ||||||
|             onPressed: () { |             onPressed: () { | ||||||
|               updateText(''); // 使用统一方法清空 |               updateText(''); | ||||||
|               onReset?.call(); |               widget.onReset?.call(); | ||||||
|             }, |             }, | ||||||
|             style: ElevatedButton.styleFrom( |             style: ElevatedButton.styleFrom( | ||||||
|               backgroundColor: Colors.blue, |               backgroundColor: Colors.blue, | ||||||
|  | @ -110,8 +124,8 @@ class SearchBarWidget extends StatelessWidget { | ||||||
|               shadowColor: Colors.black26, |               shadowColor: Colors.black26, | ||||||
|             ), |             ), | ||||||
|             child: Text( |             child: Text( | ||||||
|               resetButtonText, |               widget.resetButtonText, | ||||||
|               style: TextStyle(color: Colors.white, fontSize: 16), |               style: const TextStyle(color: Colors.white, fontSize: 16), | ||||||
|             ), |             ), | ||||||
|           ), |           ), | ||||||
|       ], |       ], | ||||||
|  |  | ||||||
|  | @ -73,7 +73,7 @@ class MyApp extends StatelessWidget { | ||||||
|           behavior: HitTestBehavior.translucent, // 让空白区域也能点击 |           behavior: HitTestBehavior.translucent, // 让空白区域也能点击 | ||||||
|           onTap: () { |           onTap: () { | ||||||
|             // 收起键盘 |             // 收起键盘 | ||||||
|             FocusScope.of(context).requestFocus(_blankFocusNode); |             FocusScope.of(context).unfocus(); | ||||||
|           }, |           }, | ||||||
|           child: child, |           child: child, | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|  | @ -76,22 +76,25 @@ class _CheckRecordPageState extends State<CheckRecordPage> { | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     // 取屏幕宽度 |     // 取屏幕宽度 | ||||||
|     final double screenWidth = MediaQuery.of(context).size.width; |     final double screenWidth = MediaQuery.of(context).size.width; | ||||||
|     final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); |  | ||||||
| 
 | 
 | ||||||
|     return Scaffold( |     return Scaffold( | ||||||
|       key: _scaffoldKey, // ② 绑定 key |  | ||||||
| 
 |  | ||||||
|       appBar: MyAppbar( |       appBar: MyAppbar( | ||||||
|         title: appBarTitle, |         title: appBarTitle, | ||||||
|         actions: [ |         actions: [ | ||||||
|           TextButton( |           // 用 Builder 拿到 Scaffold 之下的 context | ||||||
|             onPressed: () { |           Builder( | ||||||
|               _scaffoldKey.currentState?.openEndDrawer(); |             builder: (innerContext) { | ||||||
|  |               return TextButton( | ||||||
|  |                 onPressed: () { | ||||||
|  |                   // 通过 innerContext 调用 openEndDrawer | ||||||
|  |                   Scaffold.of(innerContext).openEndDrawer(); | ||||||
|  |                 }, | ||||||
|  |                 child: Text( | ||||||
|  |                   "查询", | ||||||
|  |                   style: TextStyle(color: Colors.white, fontSize: 16), | ||||||
|  |                 ), | ||||||
|  |               ); | ||||||
|             }, |             }, | ||||||
|             child: Text( |  | ||||||
|               "查询", |  | ||||||
|               style: TextStyle(color: Colors.white, fontSize: 16), |  | ||||||
|             ), |  | ||||||
|           ), |           ), | ||||||
|         ], |         ], | ||||||
|       ), |       ), | ||||||
|  | @ -145,8 +148,9 @@ class _CheckRecordPageState extends State<CheckRecordPage> { | ||||||
|             padding: EdgeInsets.all(10), |             padding: EdgeInsets.all(10), | ||||||
|             child: SearchBarWidget( |             child: SearchBarWidget( | ||||||
|               controller: _searchController, |               controller: _searchController, | ||||||
|               autoFocus: true, | 
 | ||||||
|               onSearch: (keyboard) { |               onSearch: (keyboard) { | ||||||
|  | 
 | ||||||
|                 // 输入请求接口 |                 // 输入请求接口 | ||||||
|                 _page=1; |                 _page=1; | ||||||
|                 searchKey=keyboard; |                 searchKey=keyboard; | ||||||
|  |  | ||||||
|  | @ -60,7 +60,6 @@ class _DangerWaitListPageState extends State<DangerWaitListPage> { | ||||||
| 
 | 
 | ||||||
|   // 隐患等级文本 |   // 隐患等级文本 | ||||||
|   final List<String> _levelTexts = ["重大隐患","一般隐患"]; |   final List<String> _levelTexts = ["重大隐患","一般隐患"]; | ||||||
|   final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); |  | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   void initState() { |   void initState() { | ||||||
|  | @ -101,21 +100,24 @@ class _DangerWaitListPageState extends State<DangerWaitListPage> { | ||||||
|     final double screenWidth = MediaQuery.of(context).size.width; |     final double screenWidth = MediaQuery.of(context).size.width; | ||||||
| 
 | 
 | ||||||
|     return Scaffold( |     return Scaffold( | ||||||
|       key: _scaffoldKey, // ② 绑定 key |  | ||||||
|       appBar: MyAppbar( |       appBar: MyAppbar( | ||||||
|         title: widget.dangerType.displayName, |         title: widget.dangerType.displayName, | ||||||
|         actions: [ |         actions: [ | ||||||
|           if(1==widget.appItem) |           if (1 == widget.appItem) | ||||||
|           TextButton( |             Builder( | ||||||
|             onPressed: () { |               builder: (innerContext) { | ||||||
|               // 查询 右侧弹窗页面 |                 return TextButton( | ||||||
|               _scaffoldKey.currentState?.openEndDrawer(); |                   onPressed: () { | ||||||
|             }, |                     // 通过 innerContext 拿到 ScaffoldState,打开右侧抽屉 | ||||||
|             child: Text( |                     Scaffold.of(innerContext).openEndDrawer(); | ||||||
|               "查询", |                   }, | ||||||
|               style: TextStyle(color: Colors.white, fontSize: 16), |                   child: Text( | ||||||
|  |                     "查询", | ||||||
|  |                     style: TextStyle(color: Colors.white, fontSize: 16), | ||||||
|  |                   ), | ||||||
|  |                 ); | ||||||
|  |               }, | ||||||
|             ), |             ), | ||||||
|           ), |  | ||||||
|         ], |         ], | ||||||
|       ), |       ), | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -39,7 +39,6 @@ class _RiskControlPageState extends State<RiskControlPage> { | ||||||
| 
 | 
 | ||||||
|   // 风险等级文本 |   // 风险等级文本 | ||||||
|   final List<String> _levelTexts = ["重大风险/A级", "较大风险/B级", "一般风险/C级", "低风险/D级"]; |   final List<String> _levelTexts = ["重大风险/A级", "较大风险/B级", "一般风险/C级", "低风险/D级"]; | ||||||
|   final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|  | @ -59,19 +58,23 @@ class _RiskControlPageState extends State<RiskControlPage> { | ||||||
|     final double screenWidth = MediaQuery.of(context).size.width; |     final double screenWidth = MediaQuery.of(context).size.width; | ||||||
| 
 | 
 | ||||||
|     return Scaffold( |     return Scaffold( | ||||||
|       key: _scaffoldKey, // ② 绑定 key |  | ||||||
|       appBar: MyAppbar( |       appBar: MyAppbar( | ||||||
|         title: "风险分布", |         title: "风险分布", | ||||||
|         actions: [ |         actions: [ | ||||||
|           TextButton( |           // 用 Builder 拿到 Scaffold 之下的 context | ||||||
|             onPressed: () { |           Builder( | ||||||
|               // 查询 右侧弹窗页面 |             builder: (innerContext) { | ||||||
|               _scaffoldKey.currentState?.openEndDrawer(); |               return TextButton( | ||||||
|  |                 onPressed: () { | ||||||
|  |                   // 通过 innerContext 调用 openEndDrawer | ||||||
|  |                   Scaffold.of(innerContext).openEndDrawer(); | ||||||
|  |                 }, | ||||||
|  |                 child: Text( | ||||||
|  |                   "查询", | ||||||
|  |                   style: TextStyle(color: Colors.white, fontSize: 16), | ||||||
|  |                 ), | ||||||
|  |               ); | ||||||
|             }, |             }, | ||||||
|             child: Text( |  | ||||||
|               "查询", |  | ||||||
|               style: TextStyle(color: Colors.white, fontSize: 16), |  | ||||||
|             ), |  | ||||||
|           ), |           ), | ||||||
|         ], |         ], | ||||||
|       ), |       ), | ||||||
|  |  | ||||||
							
								
								
									
										290
									
								
								pubspec.lock
								
								
								
								
							
							
						
						
									
										290
									
								
								pubspec.lock
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
		Reference in New Issue