flutter 的searchBar,按照公司项目需求自己写了个。先看效果图:
可以看到searchBar分为两个不同的状态,一个是不聚焦的状态,一个是聚焦的状态。组件属性说明:
final String hintText;//占位字符
final onSearch;//点击搜索和键盘的搜索按钮触发时间,返回搜索框里输入的文字
final bool showCancleBtn;//是否显示右边的取消/搜索按钮
具体实现
1、在state
里定义textField
相关的属性
//输入框控制器
final TextEditingController _controller = TextEditingController(text: '');
//输入框node
final FocusNode _node = FocusNode();
//是否在输入中
bool _isInput = false;
2、主要界面实现
2-1、在build
里面实现界面展示代码
@override
Widget build(BuildContext context) {
// 如果允许输入且输入框没有输入内容,则聚焦。否则不做操作
if (_isInput && _controller.text.isEmpty) {
FocusScope.of(context).requestFocus(_node);
}
return Container(
padding: EdgeInsets.only(
top: 8,
bottom: 8,
left: 16,
right: (!widget.showCancleBtn || !_isInput) ? 16 : 0),
color: Theme.of(context).scaffoldBackgroundColor,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: GestureDetector(
onTap: () {
setState(() {
_isInput = true;
});
},
child: Container(
height: 30,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4),
border: Border.all(
color: Color.fromRGBO(0, 0, 0, 0.1), width: 1)),
child: _isInput ? _buildInput() : _buildNoInput(),
),
),
),
(widget.showCancleBtn && (_controller.text.isNotEmpty || _isInput))
? InkWell(
onTap: () {
if (_controller.text.isNotEmpty && !_node.hasFocus) {
if (widget.onSearch != null) {
widget.onSearch(_controller.text);
}
} else {
_node.unfocus();
}
},
child: Container(
width: 56,
height: 26,
alignment: Alignment.center,
child: Text(
(_controller.text.isNotEmpty && !_node.hasFocus)
? '搜索'
: '取消',
style: TextStyle(
fontSize: 14,
height: 1.4,
color: Theme.of(context).primaryColor),
),
))
: SizedBox(
width: 0,
)
],
),
);
}
2-2、不在输入状态且输入框没有输入文字的时候展示的界面代码
Widget _buildNoInput() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(
Icons.search,
color: Color.fromRGBO(0, 0, 0, 0.2),
size: 14,
),
SizedBox(
width: 4,
),
Text(
widget.hintText,
style: TextStyle(color: Color.fromRGBO(0, 0, 0, 0.2), fontSize: 12),
)
],
);
}
2-3、输入状态下界面代码
Widget _buildInput() {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
width: 8,
),
Icon(
Icons.search,
color: Color.fromRGBO(0, 0, 0, 0.2),
size: 14,
),
SizedBox(
width: 4,
),
Expanded(
child: Container(
height: 30,
child: TextField(
style:
TextStyle(color: Color.fromRGBO(0, 0, 0, 0.8), fontSize: 12),
controller: _controller,
focusNode: _node,
autofocus: true,
textInputAction: TextInputAction.search,
onEditingComplete: () {
if (_controller.text.isNotEmpty) {
_node.unfocus();
if (widget.onSearch != null) {
widget.onSearch(_controller.text);
}
} else {
_node.unfocus();
}
},
decoration: InputDecoration(
contentPadding: EdgeInsets.only(top: -18),
hintText: widget.hintText,
hintStyle: TextStyle(
fontSize: 12, color: Color.fromRGBO(0, 0, 0, 0.2)),
border: InputBorder.none,
fillColor: Colors.red),
),
),
)
],
);
}
为了做到点击取消或者点击键盘搜索按钮能取消聚焦且判断界面展示,就需要监听输入框TextField是否聚焦的状态,这个时候,在InitState
里面进行监听。
_node.addListener(() {
debugPrint(
'-------------${_controller.text.isEmpty}---${_node.hasFocus}');
if (!_node.hasFocus) {
// 失去焦点
setState(() {
_isInput = _controller.text.isEmpty ? false : true;
});
} else {}
});
实现searchBar完成了,这个只是针对公司项目开发的一个组件,后续会做个AppBar内置搜索框的组件。
附上项目地址:HGSearchBar