QinGang_interested/lib/customWidget/search_bar_widget.dart

164 lines
5.2 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import 'package:flutter/material.dart';
class SearchBarWidget extends StatefulWidget {
final String hintText;
final String buttonText;
final ValueChanged<String> onSearch;
final TextEditingController controller;
final bool showResetButton;
final String resetButtonText;
final VoidCallback? onReset;
final bool isClickableOnly;
final VoidCallback? onInputTap;
final ValueChanged<String>? 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<SearchBarWidget> {
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),
),
),
),
],
);
}
}