flutter - 试图制定一个公式来计算 2 个 dateTimes 之间的时间以在 Flutter 中激活 Dark Theme
问题描述
这不是关于 Flutter 的问题,而是关于 Dart 和数学的问题。
当用户打开自动黑暗主题开关或返回应用程序时,我试图自己制作我的应用程序主题。
我已经为用户设置了更改自动黑暗主题的初始时间和结束时间的选项,这为我们提供了DateTime()变量,其中包含年、月、日、小时、分钟、秒等数据。 ( 24 小时制的小时数)
现在我有这个公式:
if ((now.hour >= _startTime.hour && now.minute >= _startTime.minute) || (now.hour <= _endTime.hour && now.minute <= _endTime.minute)) {
setTheme('dark');
} else {
setTheme('light');
}
我认为它工作得很好,但正如你在这张图片和设置中看到的那样。它没有正常工作......
这些是变量:
_startTime = 1:00 AM = 1
now = 10:40PM = 22:40
_endTime = 8:00 AM = 8
通过使用我的公式:((now.hour >= _startTime.hour && now.minute >= _startTime.minute) || (now.hour <= _endTime.hour && now.minute <= _endTime.minute))
这会创建一个True和一个False,它们等于True并激活黑暗主题。
我怎样才能完善这个公式?这似乎很容易做到,但实际上非常混乱。
编辑:对于那些喜欢处理数字的人
让我们从选择器(允许用户输入日期或时间的小部件)开始
class HourPickers extends StatelessWidget {
@override
Widget build(BuildContext context) {
CustomAppThemeProvider themeProvider =
Provider.of<CustomAppThemeProvider>(context, listen: false);
DateTime startTime = themeProvider.getStartTime;
DateTime endTime = themeProvider.getEndTime;
print('from provider:\n$startTime & $endTime');
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Switch(
value: themeProvider.getIsAutoThemeSwitchOn,
activeColor: Colors.green,
onChanged: (boolean) {
themeProvider.setIsAutoThemeSwitchOn(boolean);
},
),
Text(
'Tema Oscuro Automático',
style: Theme.of(context).textTheme.subtitle,
),
],
),
Text(
'Inicio',
style: Theme.of(context).textTheme.subtitle,
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 5),
child: SizedBox(
height: 100,
child: Card(
child: CupertinoDatePicker(
mode: CupertinoDatePickerMode.time,
initialDateTime: DateTime(startTime.year, startTime.month,
startTime.day, startTime.hour, startTime.minute),
onDateTimeChanged: (DateTime pickedTime) {
Provider.of<CustomAppThemeProvider>(context, listen: false)
.setStartTime(pickedTime);
},
use24hFormat: false,
backgroundColor: Theme.of(context).colorScheme.primary,
),
),
),
),
Text(
'Final',
style: Theme.of(context).textTheme.subtitle,
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 5),
child: SizedBox(
height: 100,
child: Card(
child: CupertinoDatePicker(
mode: CupertinoDatePickerMode.time,
initialDateTime: DateTime(endTime.year, endTime.month,
endTime.day, endTime.hour, endTime.minute),
onDateTimeChanged: (DateTime pickedTime) {
Provider.of<CustomAppThemeProvider>(context, listen: false)
.setEndTime(pickedTime);
},
use24hFormat: false,
backgroundColor: Theme.of(context).colorScheme.primary,
),
),
),
),
],
),
);
}
}
这就是提供者去的地方(我刚刚取出了主题部分)
bool get getIsAutoThemeSwitchOn => _isAutoThemeSwitchOn;
Future<bool> getPrefIsAutoThemeSwitchOn() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool _prefAutoTheme = prefs.getBool('AutoTheme') ?? false;
_isAutoThemeSwitchOn = _prefAutoTheme;
return _prefAutoTheme;
}
Future<void> setIsAutoThemeSwitchOn(boolean) async {
_isAutoThemeSwitchOn = boolean;
// print(_isAutoThemeSwitchOn);
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool('AutoTheme', boolean);
if (boolean == true) {
autoThemeSetter();
} else {
notifyListeners();
}
}
void autoThemeSetter() {
// only if switch is ON
DateTime now = DateTime.now();
if (_startTime.isAfter(_endTime)) _endTime = _endTime.add(Duration(days: 1));
print('start: $_startTime');
print('now: $now');
print('end: $_endTime');
print('now >= start? ${now.isAfter(_startTime)}');
print('now <= end? ${now.isBefore(_endTime)}');
if (now.isAfter(_startTime) && now.isBefore(_endTime)) {
// print('auto dark theme');
setTheme('dark');
} else {
// print('auto light theme');
setTheme('light');
}
// had add notify even if switch != true because the switch value needs to update
notifyListeners();
}
getPrefTimes() async {
await getPrefsStartTime();
await getPrefsEndTime();
}
getPrefsStartTime() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
if (prefs.getInt('startTime') != null) {
DateTime now = DateTime.now();
_startTime =
DateTime.fromMillisecondsSinceEpoch(prefs.getInt('startTime'));
print('start pref: $_startTime');
// set the day equal to now.day
if (now.day != _startTime.day) {
_startTime = DateTime(now.year, now.month, now.day, _startTime.hour, _startTime.minute);
}
// sub -1 day if needed
if (_startTime.isAfter(now)) _startTime = _startTime.subtract(Duration(days: 1));
// update SharedPref because why not
// setStartTime(_startTime);
}
}
getPrefsEndTime() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
if (prefs.getInt('endTime') != null) {
DateTime now = DateTime.now();
_endTime = DateTime.fromMillisecondsSinceEpoch(prefs.getInt('endTime'));
print('end pref: $_endTime');
// set the day equal to now.day
if (now.day != _endTime.day) {
_endTime = DateTime(now.year, now.month, now.day, _endTime.hour, _endTime.minute);
}
// add +1 day if needed
if (_startTime.isAfter(_endTime)) _endTime = _endTime.add(Duration(days: 1));
// update SharedPref because why not
// setStartTime(_endTime);
}
}
get getStartTime => _startTime;
get getEndTime => _endTime;
Future<void> setStartTime(DateTime pickedTime) async {
// print(pickedTime);
SharedPreferences prefs = await SharedPreferences.getInstance();
DateTime now = DateTime.now();
_startTime = pickedTime;
// sub -1 day if needed
if (_startTime.isAfter(now)) _startTime = _startTime.subtract(Duration(days: 1));
int epoch = _startTime.millisecondsSinceEpoch;
prefs.setInt('startTime', epoch);
// print(prefs.getInt('startTime'));
}
Future<void> setEndTime(DateTime pickedTime) async {
// print(pickedTime);
SharedPreferences prefs = await SharedPreferences.getInstance();
DateTime now = DateTime.now();
_endTime = pickedTime;
// sub -1 day if needed
if (_startTime.isAfter(now)) _startTime = _startTime.subtract(Duration(days: 1));
int epoch = _endTime.millisecondsSinceEpoch;
prefs.setInt('endTime', epoch);
}
}
您已经可以看到这并不像看起来那么容易,只有自动主题切换器的背景有很多。
顺便说一句,每次应用程序从后台恢复时都会调用 autoThemeSetter()。
解决方案
您使用的公式存在一些逻辑缺陷。主要是,它不检查 now 是否在 _startTime 和 _endTime 之间(OR 应该是 AND ......但仍然存在问题)
只是为了解释起见,您使用的逻辑是“如果当前时间在开始时间之后或者如果当前时间在结束时间之前,则使主题变暗”
假设当前时间是上午 9 点,开始时间是上午 1 点,结束时间是上午 8 点。这会将主题设置为深色,因为您使用了 OR,而上午 9 点是在凌晨 1 点之后。因此,它通过了,因为 OR 不是关于它在 endTime 之后的事实。因此,您需要使用 && 来检查两者,因为您想检查当前时间是否在 _startTime 之后和 _endTime 之前。
不幸的是,你不能把它变成一个 && 并称之为一天,因为小时和分钟是分开的。所以,假设时间是早上 6 点 01 分......并且开始和结束与之前相同。在这种情况下,第一部分为真(当前时间分钟和小时大于 _startTime 分钟和小时,但它会将主题设置为 LIGHT,因为当前分钟(01)不小于 _endTime 分钟,尽管它很明显在范围内。
因此,一种选择是将所有内容转换为分钟,如下所示:
if ((now.hour * 60 + now.minute) >=
(_startTime.hour * 60 + _startTime.minute) &&
((now.hour * 60 + now.minute) <=
(_endTime.hour * 60 + _endTime.minute))) {
print('dark');
} else {
print('light');
}
但这有不检查日期的缺点。例如,如果您希望开始时间为 2300 并且停止时间为 0800,则它将不起作用。
另一种(更好的)方法是使用 .isBefore() 和 .isAfter() 方法。但是,您需要确保他们使用正确的日期,因为您使用的是 DateTime() 对象。这可能看起来像:
var stringDate = DateTime.now().year.toString() + "-" + DateTime.now().month.toString().padLeft(2, '0') + "-" + DateTime.now().day.toString().padLeft(2, '0');
//I'm assuming that all dates are the same, but you should use the correct dates.
print(stringDate);
var now_2 = DateTime.now();
var _startTime_2 = DateTime.parse(stringDate + " 01:00:00Z");
var _endTime_2 = DateTime.parse(stringDate+" 08:00:00Z");
print("now_2="+now_2.toString());
print("_startTime_2="+_startTime_2.toString());
print("_endTime_2="+_endTime_2.toString());
print("inBefore method");
print("---------------------------------");
if (_startTime_2.isBefore(now_2) && now_2.isBefore(_endTime_2)) {
print('dark');
} else {
print('light');
}
我制作了一个 dartpad 文件,以便您可以在此处使用代码: https ://dartpad.dev/1f978458eabcaf588c872fa4f6bfdaf0
推荐阅读
- angular - 如何在不“弹出”的情况下在 Angular 构建中导入和转译 es6 模块
- javascript - getElementsByClassName 如何获取带有链接的html元素?
- html - 由多个 div 和 span 组成的控件的 Aria 音频描述不起作用
- git - git log 不显示所有提交
- java - android中的全屏意图到底是什么?
- powershell - Powershell递归写入同一目录
- vim - 更改任何字符内的文本(如 ci')
- c# - 有没有办法找到特定应用程序的 uID?
- python - 从 Python 数据类动态创建 Pydantic 模型
- html - 我可以回去吗?在 Visual Studio 代码中查看版本历史?