import 'package:flutter/material.dart'; class SearchBarWidget extends StatefulWidget { final String hintText; final String buttonText; final ValueChanged onSearch; final TextEditingController controller; final bool showResetButton; final String resetButtonText; final VoidCallback? onReset; final bool isClickableOnly; final VoidCallback? onInputTap; final ValueChanged? onTextChanged; final bool isShowSearchButton; final double height; // 新增:可配置高度 const SearchBarWidget({ Key? key, required this.onSearch, required this.controller, this.hintText = '请输入关键字', this.buttonText = '搜索', this.showResetButton = false, this.resetButtonText = '重置', this.onReset, this.isClickableOnly = false, this.onInputTap, this.onTextChanged, this.isShowSearchButton = true, this.height = 40.0, // 默认更紧凑的高度 }) : super(key: key); @override _SearchBarWidgetState createState() => _SearchBarWidgetState(); } class _SearchBarWidgetState extends State { late FocusNode _focusNode; @override void initState() { super.initState(); _focusNode = FocusNode(); } @override void dispose() { _focusNode.dispose(); super.dispose(); } /// 更新输入框内容(可在外部调用) void updateText(String newText) { widget.controller.text = newText; widget.controller.selection = TextSelection.fromPosition( TextPosition(offset: newText.length), ); widget.onTextChanged?.call(newText); } @override Widget build(BuildContext context) { // 计算 contentPadding,使文本垂直居中 final innerHeight = widget.height; // 文本行高大约 20 左右,留出少量上下内边距 final verticalPadding = (innerHeight - 20).clamp(0.0, innerHeight) / 2; return Row( children: [ Expanded( child: SizedBox( height: innerHeight, child: TextField( focusNode: _focusNode, controller: widget.controller, readOnly: widget.isClickableOnly, autofocus: false, style: const TextStyle(fontSize: 14), onChanged: widget.onTextChanged, onTap: () { if (widget.isClickableOnly) { widget.onInputTap?.call(); } }, decoration: InputDecoration( filled: true, fillColor: const Color(0xFFF5F5F5), prefixIcon: Row( mainAxisSize: MainAxisSize.min, children: [ const SizedBox(width: 12), Image.asset('assets/images/search.png', height: 15, width: 15,) ], ), // 控制 prefixIcon 的约束,保证图标不会撑高 prefixIconConstraints: const BoxConstraints( minWidth: 32, minHeight: 32, ), hintText: widget.hintText, border: OutlineInputBorder( borderRadius: BorderRadius.circular(5), borderSide: BorderSide.none, ), isDense: true, contentPadding: EdgeInsets.symmetric( vertical: verticalPadding, horizontal: 8, ), ), onSubmitted: widget.onSearch, ), ), ), const SizedBox(width: 10), if (widget.isShowSearchButton) SizedBox( height: innerHeight - 4, // 稍微比 TextField 矮一点看着更协调 child: ElevatedButton( onPressed: () => widget.onSearch(widget.controller.text.trim()), style: ElevatedButton.styleFrom( backgroundColor: Colors.blue, padding: const EdgeInsets.symmetric(horizontal: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5), ), elevation: 4, shadowColor: Colors.black45, ), child: Text( widget.buttonText, style: const TextStyle(color: Colors.white, fontSize: 14), ), ), ), if (widget.showResetButton) const SizedBox(width: 10), if (widget.showResetButton) SizedBox( height: innerHeight - 4, child: ElevatedButton( onPressed: () { updateText(''); widget.onReset?.call(); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.blue, padding: const EdgeInsets.symmetric(horizontal: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5), ), elevation: 1, shadowColor: Colors.black26, ), child: Text( widget.resetButtonText, style: const TextStyle(color: Colors.white, fontSize: 14), ), ), ), ], ); } }