Это не вопрос флаттера, а вопрос дротика и математики.
Я пытаюсь создать тему для своего приложения, когда пользователь включает автоматическую темную тему. переключиться, или когда он вернется в приложение.
Я уже установил опцию для пользователя, чтобы изменить начальное время и время окончания автоматического Темная тема дает нам DateTime () переменные, которые содержат данные год, месяц, день, час, минуты, секунды и т. д. c. (часы в 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 () вызывается каждый раз, когда приложение возобновляет работу из фона.