Flutter中如何将用户选择的TimeOfDay应用到本地定时通知?
Alright, let's fix this so your notification triggers exactly at the time the user picks with the time picker. Here's how to adjust your code step by step:
1. Add a helper method to convert TimeOfDay to TZDateTime
The zonedSchedule method requires a timezone-aware datetime (not just hours and minutes), so we need to turn the user's selected TimeOfDay into a full TZDateTime object. We also need to handle cases where the selected time has already passed today—we'll schedule it for tomorrow instead to avoid immediate, unintended triggers.
TZDateTime _convertTimeOfDayToTZDateTime(TimeOfDay selectedTime) { final now = tz.TZDateTime.now(tz.local); // Create a datetime for today at the selected hour/minute var scheduledDate = tz.TZDateTime( tz.local, now.year, now.month, now.day, selectedTime.hour, selectedTime.minute, ); // If the selected time is already in the past today, use tomorrow's date if (scheduledDate.isBefore(now)) { scheduledDate = scheduledDate.add(const Duration(days: 1)); } return scheduledDate; }
2. Modify your notification scheduling method
Replace your existing firstNotifications method with one that uses the converted datetime from the user's selection. I've renamed it to something more descriptive, and added optional title/body text since your original had null values (you can customize these as needed):
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); final mymodel = myModel(); Future<void> scheduleNotificationAtSelectedTime() async { // Initialize notifications as before var initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/ic_launcher'); var initializationSettings = InitializationSettings(android: initializationSettingsAndroid); await flutterLocalNotificationsPlugin.initialize(initializationSettings); // Keep your existing notification details const AndroidNotificationDetails firstNotificationSpecifics = AndroidNotificationDetails( 'channel id', 'channel name', 'channel description', sound: RawResourceAndroidNotificationSound('song1'), playSound: true, enableVibration: false, visibility: NotificationVisibility.secret, autoCancel: true, timeoutAfter: 7000, ); const NotificationDetails firstNotificationPlatformSpecifics = NotificationDetails(android: firstNotificationSpecifics); // Convert the user's selected TimeOfDay to a schedulable datetime final scheduledTime = _convertTimeOfDayToTZDateTime(mymodel.selectedTime); // Schedule the notification at the converted time await flutterLocalNotificationsPlugin.zonedSchedule( 1, 'Scheduled Reminder', // Customize notification title 'Your notification is triggered at the time you selected!', // Customize notification body scheduledTime, firstNotificationPlatformSpecifics, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, androidAllowWhileIdle: true, // Uncomment this line if you want the notification to repeat daily at the same time // repeatInterval: RepeatInterval.daily, ); }
3. Trigger the schedule when the user selects a time
Update your selectTime method to call the new scheduling function right after the user picks a time and saves it:
Future<Null> selectTime(BuildContext context) async { final picked = await showTimePicker( context: context, initialTime: model.selectedTime, ); if (picked != null){ setState(() { model.selectedTime = picked; this.preferences?.setString("dateValue", model.selectedTime.format(context)); // Schedule the notification immediately after saving the selected time scheduleNotificationAtSelectedTime(); }); } }
Key Notes:
- Timezone Awareness: Using
tz.TZDateTimeensures your notification works correctly across different timezones, which is crucial for reliable scheduling. - Past Time Handling: The helper method checks if the selected time has already passed today—if so, it schedules for tomorrow instead of triggering instantly.
- Repeat Option: If you want the notification to repeat daily at the selected time, uncomment the
repeatIntervalline in the scheduling method.
内容的提问来源于stack exchange,提问作者kacola2115

