效果图如下

封装了一个 SearchAppBarWidget
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutterapp/common/ColorsUtil.dart';
class SearchAppBarWidget extends StatefulWidget implements PreferredSizeWidget {
final double height;
final double elevation; //阴影
final Widget leading;
final String hintText;
final FocusNode focusNode;
final TextEditingController controller;
final IconData prefixIcon;
final List<TextInputFormatter> inputFormatters;
final VoidCallback onEditingComplete;
const SearchAppBarWidget(
{Key key,
this.height: 46.0,
this.elevation: 0.5,
this.leading,
this.hintText: '搜索',
this.focusNode,
this.controller,
this.inputFormatters,
this.onEditingComplete,
this.prefixIcon: Icons.search})
: super(key: key);
@override
State<StatefulWidget> createState() {
return new SearchAppBarState();
}
///这里设置控件(appBar)的高度
@override
Size get preferredSize => Size.fromHeight(height);
}
class SearchAppBarState extends State<SearchAppBarWidget> {
bool _hasDeleteIcon = false;
@override
Widget build(BuildContext context) {
return new PreferredSize(
child: new Stack(
children: <Widget>[
Offstage(
offstage: false,
child:
MoreWidgets.buildAppBar(context, '', leading: widget.leading),
),
Offstage(
offstage: false,
child: Flex(
direction: Axis.horizontal,
children: <Widget>[
Expanded(
child: Container(
height: 70,
margin: EdgeInsets.only(left: 10),
padding: const EdgeInsets.only(left: 0.0, top: 36.0),
child: new TextField(
focusNode: widget.focusNode,
/// 键盘类型
keyboardType: TextInputType.text,
///控制键盘的功能键 指enter键,比如此处设置为next时,enter键
textInputAction: TextInputAction.search,
controller: widget.controller,
maxLines: 1,
inputFormatters: widget.inputFormatters,
decoration: InputDecoration(
hintText: widget.hintText,
hintStyle: TextStyle(
color: Colors.black,
fontSize: 16.5,
),
suffixIcon: Container(
padding: EdgeInsetsDirectional.only(
start: 2.0,
end: _hasDeleteIcon ? 0.0 : 0,
),
child: _hasDeleteIcon
? new InkWell(
onTap: (() {
setState(() {
/// 保证在组件build的第一帧时才去触发取消清空内容
WidgetsBinding.instance.addPostFrameCallback((_) => widget.controller.clear());
_hasDeleteIcon = false;
});
}),
child: Icon(
Icons.cancel,
size: 18.0,
color: Colors.grey,
),
)
: new Text(''),
),
contentPadding: EdgeInsets.fromLTRB(30, 10, 0, 0),
filled: true,
fillColor: ColorsUtil.grey(),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide.none,
),
),
onChanged: (str) {
setState(() {
if (str.isEmpty) {
_hasDeleteIcon = false;
} else {
_hasDeleteIcon = true;
}
});
},
onEditingComplete: widget.onEditingComplete,
),
),
),
/// 取消按钮
InkWell(
child: Container(
alignment: Alignment.center,
padding: EdgeInsets.only(top: 36, left: 10, right: 10),
child: Text(
'取消',
style: TextStyle(
fontSize: 18,
),
),
),
onTap: () {
// Navigator.of(context).pop();
},
),
],
),
),
/// 搜索图标 (可以在TextField prefixIcon 可以直接定义icon)
Positioned(
left: 16,
top: 45,
child: Image(
width: 16,
height: 16,
image: AssetImage(
"images/Icon/btn_seach@2x.png",
),
color: ColorsUtil.fromHex('#333333'),
),
),
],
),
preferredSize: Size.fromHeight(widget.height),
);
}
}
/// 控件点击时触发
typedef OnItemDoubleClick = Future<void> Function(Object);
/// 生成常用的AppBar
class MoreWidgets {
static Widget buildAppBar(
BuildContext context,
String text, {
double fontSize: 18.0,
double height: 50.0,
double elevation: 0.5,
Widget leading,
bool centerTitle: false,
List<Widget> actions,
OnItemDoubleClick onItemDoubleClick,
}) {
return PreferredSize(
child: GestureDetector(
onDoubleTap: () {
if (null != onItemDoubleClick) {
onItemDoubleClick(null);
}
},
child: AppBar(
backgroundColor: Colors.white,
elevation: elevation,
//阴影
centerTitle: centerTitle,
title: Text(text, style: TextStyle(fontSize: fontSize)),
leading: leading,
actions: actions,
)),
preferredSize: Size.fromHeight(height),
);
}
}
使用方法如下
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutterapp/searchBar/SearchAppBarWidget.dart';
class SearchDemo extends StatefulWidget {
@override
_SearchDemoState createState() => _SearchDemoState();
}
class _SearchDemoState extends State<SearchDemo> {
FocusNode _focusNode;
TextEditingController _controller;
String _searchText;
@override
void initState() {
super.initState();
_focusNode = FocusNode();
_controller = TextEditingController();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: new SearchAppBarWidget(
focusNode: _focusNode,
controller: _controller,
elevation: 2.0,
// leading: IconButton(
// icon: Icon(Icons.arrow_back),
// onPressed: () {
// Navigator.pop(context);
// },
// ),
inputFormatters: [
LengthLimitingTextInputFormatter(150),
],
onEditingComplete: () {
print('搜索框输入的内容是: ${_controller.text}');
setState(() {
_searchText = _controller.text;
});
_focusNode.unfocus();
},
),
body: Center(
child: Text("搜索内容: $_searchText"),
)
);
}
}
以上代码仅供参考,大家可以按照各自的需求去修改 SearchAppBarWidget 里面的代码,实现不同的效果。
