效果图:
这个函数接收两个参数:
第一个参数context上下文
第二个参数contentMap(这个参数主要作用就是接收你需要搜索的东西,生成输入框或者选择器或者日期选择 这里暂时只有这几种,后期有需要可以在下面 “循环生成输入框” 的方法中增加判断生成其他类型的控件)
※在封装的时候我是另外创建的一个文件utils.dart,然后直接写方法所以就没有状态,就意味着在里面无法使用setState方法,(就算不是另外创建的一个文件,在原来的页面中创建这个方法虽然有setState方法但是,由于使用了"showDialog"就相当于是重新打开了一个页面,你在setState也是没有效果的,就相当于你拿前朝的剑来斩本朝的官,这不现实啊),解决办法就是在需要刷新状态的组件外面再套一个有状态的组件不就行了吗StatefulBuilder,但是定义状态不能定义到StatefulBuilder里面去,因为状态一更新重新执行一遍StatefulBuilder里面的代码,所以定义的状态又变回去了,然后我就直接将date1定义到StatefulBuilder外面然后就好使了,从昨天下午一直研究到今天早上,终究还是有收获的嘛!!!
import 'package:find_dropdown/find_dropdown.dart';// 搜索框使用到的插件find_dropdown: ^1.0.0
funshowAlertDialog(BuildContext context, contentMap) async {
// 当前时间
DateTime _nowDate = DateTime.now();
bool flag = false;
//设置按钮
Widget cancelButton = Container(
margin: EdgeInsets.only(right: 10),
child: InkWell(
child: Text("取消"),
onTap: () {
Navigator.pop(context);
},
),
);
Widget continueButton = Container(
child: InkWell(
child: Text(
"搜索",
style: TextStyle(color: Colors.blue),
),
onTap: () {
flag = true;
Navigator.of(context).pop('123456');
},
),
);
// 循环生成输入框
List<Widget> _funCreateWidget() {
List<Widget> widgetList = [];
contentMap.forEach((item) {
if (item['type'] == 'textFile') {
widgetList.add(
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(item['key']),
Container(
margin: EdgeInsets.only(left: 5, bottom: 5),
width: 183,
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
hintText: '请输入',
hintStyle: TextStyle(fontSize: 16.0),
),
onChanged: (e) {
item['words'] = e;
},
),
),
],
),
);
} else if(item['type']=='date'){
String date1 = '请选择';
widgetList.add(StatefulBuilder(builder: (context, setstA) {
print('重新渲染');
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(item['key']),
Container(
margin: EdgeInsets.fromLTRB(5,11.5,5,11.5),
width: 180,
// decoration: BoxDecoration(border: Border.all(color: Colors.grey,width: 1)),
child: InkWell(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('$date1'),
Icon(
Icons.arrow_forward_ios_rounded,
color: Colors.grey,
)
],
),
onTap: () async {
var res = await showDatePicker(
// 上下文环境
context: context,
// 初始化时间
initialDate: _nowDate,
// 最早时间
firstDate: DateTime(1980),
// 最晚时间
lastDate: DateTime(2100),
);
print('选择日期');
print(res.toString());
item['nm'] = res.toString().substring(0, 10);
setstA(() {
date1 = res.toString().substring(0, 10);
});
print(item);
},
)),
],
);
}));
}
else {
List<String> dropList = [];
item['dropDownList'].forEach((item) {
dropList.add(item['subCodeNm']);
});
widgetList.add(
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(item['key']),
Container(
margin: EdgeInsets.only(left: 5, bottom: 5),
width: 183,
child: FindDropdown(
searchHint: '搜索',
items: dropList,
onChanged: (e) {
for (var itema in item['dropDownList']) {
if (itema['subCodeNm'] == e) {
// print(itema);
item['nm'] = itema['subCodeNm'];
item['code'] = itema['subCode'];
// print(item.toString());
return;
}
}
},
selectedItem: "请选择",
),
),
],
),
);
}
});
return widgetList;
}
//设置对话框
AlertDialog alert = AlertDialog(
title: Text("筛选"),
contentPadding: EdgeInsets.fromLTRB(10, 10, 10, 10),
content: Container(
height: 60.0 * contentMap.length,
child: Column(
children: _funCreateWidget(),
),
),
actions: [
cancelButton,
continueButton,
],
);
//显示对话框
return await showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
).then((value) {
print('对话框即将关闭');
if (flag) {
// 判断是不是点击可了搜索
return contentMap; // 点击了搜索就返回内容
} else {
return ''; // 点击了取消就返回空
}
});
}
调用筛选:
只需要在组件的点击事件中调用此方法就能弹出筛选框
例:
IconButton(
icon: const Icon(Icons.filter_alt_outlined),
tooltip: '筛选',
onPressed: () {
funshowAlertDialog(context, [
{
'key': '调拨方',
'type': 'dropDown',
'nm': '请选择',
'code': '',
'dropDownList': [
{'subCodeNm': '1', 'subCode': '1'},
{'subCodeNm': '2', 'subCode': '2'},
{'subCodeNm': '3', 'subCode': '3'}
]// 注意这里的对象的属性必须叫"subCodeNm"和"subCode",如果你看懂了上面的封装,如果想改属性名那么这两个地方的属性名必须一致
},
{
'key': '调拨日期',
'type': 'date',
'nm': '',
},
{
'key': '船名',
'type': 'textFile',
'words':'',
},
]).then((res) {
// 这里的res就是你传入的数据选择或者输入之后的结果
// 如果type是"dropDown"那么该对象的"nm"属性对应的值就是下拉框选择的"subCodeNm"的值,该对象的"code"属性对应的值就是下拉框选择的"subCode"的值
// 如果type是date那么该对象的"nm"属性就是你选择的日期
// 如果type是textFile那么该对象的"words"属性就是你所输入的值
print('*************');
print(res);
print('*************');
});
},
)