flutter 的searchBar,按照公司項目需求自己寫了個翻斟。先看效果圖:
可以看到searchBar分為兩個不同的狀態(tài),一個是不聚焦的狀態(tài)递惋,一個是聚焦的狀態(tài)。組件屬性說明:
final String hintText;//占位字符
final onSearch;//點擊搜索和鍵盤的搜索按鈕觸發(fā)時間溢陪,返回搜索框里輸入的文字
final bool showCancleBtn;//是否顯示右邊的取消/搜索按鈕
具體實現(xiàn)
1萍虽、在state
里定義textField
相關的屬性
//輸入框控制器
final TextEditingController _controller = TextEditingController(text: '');
//輸入框node
final FocusNode _node = FocusNode();
//是否在輸入中
bool _isInput = false;
2、主要界面實現(xiàn)
2-1形真、在build
里面實現(xiàn)界面展示代碼
@override
Widget build(BuildContext context) {
// 如果允許輸入且輸入框沒有輸入內(nèi)容杉编,則聚焦。否則不做操作
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没酣、不在輸入狀態(tài)且輸入框沒有輸入文字的時候展示的界面代碼
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、輸入狀態(tài)下界面代碼
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),
),
),
)
],
);
}
為了做到點擊取消或者點擊鍵盤搜索按鈕能取消聚焦且判斷界面展示卵迂,就需要監(jiān)聽輸入框TextField是否聚焦的狀態(tài)裕便,這個時候,在InitState
里面進行監(jiān)聽见咒。
_node.addListener(() {
debugPrint(
'-------------${_controller.text.isEmpty}---${_node.hasFocus}');
if (!_node.hasFocus) {
// 失去焦點
setState(() {
_isInput = _controller.text.isEmpty ? false : true;
});
} else {}
});
實現(xiàn)searchBar完成了偿衰,這個只是針對公司項目開發(fā)的一個組件,后續(xù)會做個AppBar內(nèi)置搜索框的組件改览。
附上項目地址:HGSearchBar