前言
根据上篇的效果图和方法,再同步封装一个支持开关按钮的Cell,便于日后开发。由于功能类似,组件差不多就不再赘述。这篇主要讲添加页的实现。
选项实现
首先在循环提醒中,是有三种选项的,选项为每天时仅展示两项,选项为每周或每月则展示三项。
选项的实现用上篇封装的SSLInputRow ,选项弹窗目前采用系统自带的弹窗showTimePicker、showDatePicker和SimpleDialog 。
具体实现如下:
less
//TODO: 选择月或周
Future<int> showDayWithMonth(BuildContext context) async{
if (cycleType == 2){
//这里做判断,如果选择类型是周则弹周选项,如果是月则弹日历弹窗
int? i = await showDialog<int>(
context: context,
builder: (BuildContext context){
return SimpleDialog(
alignment: Alignment.center,
title: Text(SSLLocales.l_dream_cycle.tr),
children: [
SimpleDialogOption(
onPressed: (){
cycleTime = 1;
// warningCycleTimeStr = SSLLocales.l_dream_cycle_everyWeekOne.tr;
Get.back(result: 1);
},
child: Text(SSLLocales.l_dream_cycle_everyWeekOne.tr),
),
...重复的就不多加展示了
],
);
}
);
warningCycleTimeStr = SSLEngine.getWeekString(i??1);
debugPrint("ssl select week $i");
}else{
DateTime? timed = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(1990),
lastDate: DateTime(2100),
currentDate: DateTime.now(),
);
cycleTime = timed?.day ?? 1;
warningCycleTimeStr = cycleTime.toString().padLeft(2,"0");
}
return cycleTime;
}
//TODO: 选择当天时间
Future<String?> showDefaultTimePicker(BuildContext context, DateTime? time) async {
TimeOfDay? selectTime = await showTimePicker(
context: context,
initialTime: time != null ? TimeOfDay(hour: time.hour, minute: time.minute) : TimeOfDay.now()
);
if (selectTime == null){
return null;
}
//返回的时间样式,需要自行补0
String hour = selectTime.hour.toString().padLeft(2,"0");
String minute = selectTime.minute.toString().padLeft(2,"0");
String timeStr = "$hour:$minute:00";
return timeStr;
}
//TODO: 选择循环提醒类型
Future<int> showSelectType(BuildContext context) async{
int? i = await showDialog<int>(
context: context,
builder: (BuildContext context){
return SimpleDialog(
alignment: Alignment.center,
title: Text(SSLLocales.l_dream_cycle.tr),
children: [
SimpleDialogOption(
onPressed: (){
cycleType = 1;
warningTypeStr = SSLLocales.l_dream_cycle_everyDay.tr;
Get.back(result: 1);
},
child: Text(SSLLocales.l_dream_cycle_everyDay.tr),
),
... 重复,数据不同
],
);
}
);
//字符串显示转换,讲值转换成对应的字符串
warningCycleTimeStr = getDefaultCycleString();
return i ?? -1;
}
build中的代码展示:
less
@override
Widget build(BuildContext context) {
// TODO: implement build
return GestureDetector(
onTap: (){
debugPrint("ssl tap show time\n");//为什么不放下一层,Flutter的机制是仅有内容的区域才可响应手势,放下层无内容点击不响应
FocusScope.of(context).requestFocus(boardFocus);
},
child: Scaffold(
appBar: AppBar(
title: Text(SSLLocales.l_dream_name.tr),
leading: IconButton(
icon: Icon(Icons.arrow_back, color: sslUI.iconLeftColor,),
onPressed: (){
Get.back(result: 0);
},
),
actions: [
IconButton(onPressed: (){
saveDreamAction();
}, icon: Icon(Icons.save, color: sslUI.iconColor,))
],
),
body: Column(
children: [//标题输入
SSLInputRow(
style: SSLInputStyle.text,
title: SSLLocales.l_dream_name.tr,
inputText: dreamNameStr,
tag: 1,
callback: (tag, v){
debugPrint("ssl tap $tag $v");
dreamNameStr = v;
},
),//开关选项封装
SSLSwitchRowCell(
title: SSLLocales.l_dream_cycle_isWarning.tr,
isOn: isWarning,
valueChanged: (v){
isWarning = v;
},
),//类型选择
SSLInputRow(
inputText: warningTypeStr,
style: SSLInputStyle.arrow,
title: SSLLocales.l_dream_cycle.tr,
onTap: () async {
debugPrint("ssl tap show time picker 0$warningTypeStr\n");
int cycle = await showSelectType(context);
setState(() {
});
},
),
showCycleWidget(),//根据选择类型判断是否隐藏时间选项
SSLInputRow(
inputText: warningTimeStr,
style: SSLInputStyle.arrow,
title: SSLLocales.l_dream_time.tr,
onTap: () async {
String nowDay = SSLEngine.dateTimeYearString(DateTime.now());
//这里讲字符串转换为时间,需要注意的是字符串格式不要错了,否则会转换失败返回nil
DateTime curTime = DateTime.parse("$nowDay $warningTimeStr");
String? timeStr = await showDefaultTimePicker(context, curTime);
if (timeStr != null){
setState(() {
warningTimeStr = timeStr;
debugPrint("ssl tap show time picker $warningTimeStr\n");
});
}
},
),
const Padding(padding: EdgeInsets.only(top: 1)),
//下面的输入框
Container(//先用Container包裹,展示背景色
height: 200,
color: sslUI.cellBackColor,
child: Padding(//Padding设置边距
padding: const EdgeInsets.only(left: 15,right: 15,top: 15,bottom: 15),
child:ClipRRect(//切圆角
borderRadius: BorderRadius.circular(8),
child: Container(//改变输入背景色
color: sslUI.cellSubBackColor,
child:TextField(//具体输入的控件
controller: textControl,
textAlign: TextAlign.start,
style: TextStyle(color: sslUI.subText),
keyboardType: TextInputType.multiline,
maxLines: null,
decoration: InputDecoration(//装饰器,添加输入提示语
hintText: SSLLocales.l_input_placeholder.tr + SSLLocales.l_dream_describe.tr,
border: InputBorder.none,
fillColor: sslUI.cellBackColor
),
onChanged: (v){//输入文字回调
describeStr = v;
},
),
),
),
),
),
],
),
),
);
}
最后是保存功能
dart
void saveDreamAction() async{
//获取当前时间戳
int createTimestamp = DateTime.now().millisecondsSinceEpoch;
if (dreamId.isEmpty){//判断是新增还是修改
Map<String, dynamic> data = {//新增则创建DreamID
"dreamId" : SSLEngine.createDreamId(),
"title" : dreamNameStr,
"cycleType" : cycleType,
"cycleTime" : cycleTime,
"time" : warningTimeStr,
"subTitle" : describeStr,
"createTime" : createTimestamp,
"lastTime" : createTimestamp,
"type" : 1,
"isWarning" : isWarning,
};
int result = 0;
if (isWarning){//新增如果开启提醒则设置系统闹钟
//系统闹钟数据格式
Map<String, dynamic> info = {
"identify":data["dreamId"],
"time":data["warningTimeStr"],
"type":data["cycleType"],
"repeatTime":data["cycleTime"],
"isRepeat":true,
"title":data["title"],
"body":data["subTitle"],
"isOpen" : isWarning
};
//设置系统闹钟
result = await setAlarmClockAction(info);
if (result < 0){
}
}
//插入数据库
sslDB.insertDream(data, (int id, String value){
debugPrint("ssl create dream $id $data");
if (id > 0){
//弹窗
Fluttertoast.showToast(msg: SSLLocales.l_toast_dream_add.tr);
Get.back(result: id);
}else{
//error
}
});
}else{
//修改数据,传入之前的dreamId
Map data = {
"dreamId" : dreamId,
"title" : dreamNameStr,
"cycleType" : cycleType,
"cycleTime" : cycleTime,
"time" : warningTimeStr,
"subTitle" : describeStr,
"createTime" : createTimestamp,
"lastTime" : createTimestamp,
"type" : 1,
"isWarning" : isWarning,
};
int result = 0;
Map<String, dynamic> info = {
"identify":data["dreamId"],
"time":data["warningTimeStr"],
"type":data["cycleType"],
"repeatTime":data["cycleTime"],
"isRepeat":true,
"title":data["title"],
"body":data["subTitle"],
"isOpen" : isWarning
};
//判断是关闭还是打开闹钟
result = await setAlarmClockAction(info);
if (result < 0){
//error,比如没通知权限或者其他原因
}
//更新数据库
int count = await sslDB.updateDream(data);
if (count > 0){
DreamModel? dream = await sslDB.selectDreamById(dreamId);
if (dream != null){
//弹窗
Fluttertoast.showToast(msg: SSLLocales.l_toast_dream_update.tr);
Get.back(result: dream);
}
}else{
//error
}
}
}
以上就是全部的实现逻辑了,欢迎指正。