搜索框
效果图
代码
import 'package:flutter/material.dart';
class NovelSearch extends StatefulWidget {
State<StatefulWidget> createState() => _NovelSearchState();
}
class _NovelSearchState extends State<NovelSearch> {
String searchVal = '';
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
//清除title左右的padding,默认会有一定的距离
titleSpacing: 0,
elevation: 0,
title: SearchAppBar(
hintLabel: "搜索书名",
onSubmitted: (value) {
setState(() {
this.searchVal = value;
});
},
),
),
body: Text("搜索值是:${this.searchVal}"),
);
}
}
class SearchAppBar extends StatefulWidget {
SearchAppBar({Key? key, required this.hintLabel, required this.onSubmitted})
: super(key: key);
final String hintLabel;
// 回调函数
final Function(String) onSubmitted;
State<StatefulWidget> createState() => _SearchAppBarState();
}
class _SearchAppBarState extends State<SearchAppBar> {
// 焦点对象
FocusNode _focusNode = FocusNode();
// 文本的值
String searchVal = '';
//用于清空输入框
TextEditingController _controller = TextEditingController();
void initState() {
super.initState();
// 获取焦点
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
_focusNode.requestFocus();
});
}
Widget build(BuildContext context) {
// 获取屏幕尺寸
MediaQueryData queryData = MediaQuery.of(context);
return Container(
// 宽度为屏幕的0.8
width: queryData.size.width * 0.8,
// appBar默认高度是56,这里搜索框设置为40
height: 40,
// 设置padding
padding: EdgeInsets.only(left: 20),
// 设置子级位置
alignment: Alignment.centerLeft,
// 设置修饰
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10), color: Colors.white),
child: TextField(
controller: _controller,
// 自动获取焦点
focusNode: _focusNode,
autofocus: true,
decoration: InputDecoration(
hintText: widget.hintLabel,
hintStyle: TextStyle(color: Colors.grey),
// 取消掉文本框下面的边框
border: InputBorder.none,
icon: Padding(
padding: const EdgeInsets.only(left: 0, top: 0),
child: Icon(
Icons.search,
size: 18,
color: Theme.of(context).primaryColor,
)),
// 关闭按钮,有值时才显示
suffixIcon: this.searchVal.isNotEmpty
? IconButton(
icon: Icon(Icons.close),
onPressed: () {
// 清空内容
setState(() {
this.searchVal = '';
_controller.clear();
});
},
)
: null),
onChanged: (value) {
setState(() {
this.searchVal = value;
});
},
onSubmitted: (value) {
widget.onSubmitted(value);
},
),
);
}
}
搜索历史
效果
代码
import 'package:flutter/material.dart';
/**
* 搜索历史
*/
class SearchHistory extends StatefulWidget {
List<String> list;
final Function() clearHistory;
SearchHistory({Key? key, required this.list, required this.clearHistory})
: super(key: key) {
list.removeWhere((element) => element.isEmpty);
}
State<StatefulWidget> createState() => _SearchHistoryState();
}
class _SearchHistoryState extends State<SearchHistory> {
Widget build(BuildContext context) {
return Column(
children: [
SizedBox(
height: 30,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
//添加一个padding
Padding(
padding: EdgeInsets.only(left: 10),
child: Text(
'搜索历史',
style: TextStyle(color: Colors.grey, fontSize: 12),
),
),
// 构建一个文本按钮
GestureDetector(
onTap: () {
widget.clearHistory();
},
child: widget.list.isNotEmpty
? Padding(
padding: EdgeInsets.only(right: 10),
child: Text(
'清空历史',
style: TextStyle(
fontSize: 12,
color: Colors.grey,
),
),
)
: null,
)
],
),
),
Expanded(
child: SingleChildScrollView(
padding: EdgeInsets.all(2),
child: Wrap(
children: List.generate(
widget.list.length, (index) => _listItem(widget.list[index])),
),
),
)
],
);
}
// 构建子组件
_listItem(String title) {
// FittedBox用于调整其子部件的大小以适应可用空间
return FittedBox(
fit: BoxFit.scaleDown,
alignment: Alignment.centerLeft,
child: Container(
padding: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
margin: EdgeInsets.all(5),
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.5),
borderRadius: BorderRadius.circular(10)),
child: Text(
title,
style: TextStyle(fontSize: 12),
),
),
);
}
}