我正在开发一个 Flutter 日历应用程序,使用户能够将事件添加到特定日期。日历有效地将事件显示为日期标记,点击日期应在日历下方的列表视图中显示相应的事件。但是,我遇到了一个问题:当我点击某个日期然后返回该日期时,之前在列表视图中显示的事件消失了。事件被保存在地图中,因此程序如何输出它们可能存在问题
我使用EventList类来输出事件:
class EventList extends StatelessWidget {
final List<Event> events;
const EventList({
required this.events,
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
if (events.isEmpty) {
return Container(
padding: const EdgeInsets.all(16.0),
child: const Text(
'No Events',
style: TextStyle(color: Colors.grey),
),
);
} else {
return Expanded(
child: ListView.builder(
itemCount: events.length,
itemBuilder: (context, index) {
final event = events[index];
return Container(
margin:
const EdgeInsets.symmetric(vertical: 4.0, horizontal: 12.0),
decoration: const BoxDecoration(
color: Colors.white,
border: Border(bottom: BorderSide(color: Colors.grey)),
),
child: ListTile(
onTap: () => print(""),
title: Text(event.title),
),
);
},
),
);
}
}
}
调用类的代码:
List<Event> _getEventsForDay(DateTime day) {
return events[day] ?? [];
}
EventList(
events: _getEventsForDay(_selectedDay!),
),
这些事件看起来像是保存在地图中,但我真的不知道错误是什么。这是完整的代码
// ignore_for_file: use_build_context_synchronously
import 'package:flutter/material.dart';
import 'package:table_calendar/table_calendar.dart';
class Event {
final String title;
final DateTime dateTime;
Event(this.title, this.dateTime);
}
void main() {
runApp(const MaterialApp(
home: Calendar(),
));
}
class Calendar extends StatefulWidget {
const Calendar({Key? key}) : super(key: key);
@override
State<Calendar> createState() => _CalendarState();
}
class _CalendarState extends State<Calendar> {
final DateTime _focusedDay = DateTime.now();
DateTime? _selectedDay;
Map<DateTime, List<Event>> events = {};
final TextEditingController _eventController = TextEditingController();
@override
void initState() {
super.initState();
_selectedDay = _focusedDay;
}
List<Event> _getEventsForDay(DateTime day) {
return events[day] ?? [];
}
void _showEventInputDialog() async {
final selectedDate = await showDatePicker(
context: context,
initialDate: _focusedDay,
firstDate: DateTime(2020),
lastDate: DateTime(2030),
);
if (selectedDate != null) {
setState(() {
_selectedDay = selectedDate;
});
showModalBottomSheet(
context: context,
builder: (context) {
return Container(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Add Event - ${_selectedDay!.toString().substring(0, 10)}',
style: const TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(height: 16.0),
TextField(
controller: _eventController,
decoration: const InputDecoration(hintText: 'Event Name'),
),
const SizedBox(height: 16.0),
ElevatedButton(
onPressed: () {
if (_eventController.text.trim().isNotEmpty) {
setState(() {
final newEvent = Event(
_eventController.text.trim(),
_selectedDay!,
);
if (events[_selectedDay!] == null) {
events[_selectedDay!] = [newEvent];
} else {
events[_selectedDay!]!.add(newEvent);
}
_eventController.clear();
});
Navigator.pop(context);
}
},
child: const Text('Add Event'),
),
],
),
);
},
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Calendar'),
),
floatingActionButton: FloatingActionButton(
onPressed: _showEventInputDialog,
child: const Icon(Icons.add),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TableCalendar(
calendarBuilders: CalendarBuilders(
markerBuilder: (context, date, events) {
if (events.isNotEmpty) {
return Positioned(
bottom: 0,
child: Container(
width: 6,
height: 6,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.blue,
),
),
);
}
return const SizedBox();
},
),
availableGestures: AvailableGestures.all,
selectedDayPredicate: (day) {
return isSameDay(_selectedDay, day);
},
focusedDay: _focusedDay,
firstDay: DateTime.utc(2020, 01, 01),
lastDay: DateTime.utc(2030, 01, 01),
onDaySelected: (selectedDay, focusedDay) {
setState(() {
_selectedDay = selectedDay;
});
},
eventLoader: _getEventsForDay,
),
const SizedBox(height: 8.0),
const Divider(
indent: 4,
endIndent: 16,
thickness: 1,
color: Colors.grey,
),
EventList(
events: _getEventsForDay(_selectedDay!),
),
],
),
);
}
}
class EventList extends StatelessWidget {
final List<Event> events;
const EventList({
required this.events,
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
if (events.isEmpty) {
return Container(
padding: const EdgeInsets.all(16.0),
child: const Text(
'No Events',
style: TextStyle(color: Colors.grey),
),
);
} else {
return Expanded(
child: ListView.builder(
itemCount: events.length,
itemBuilder: (context, index) {
final event = events[index];
return Container(
margin:
const EdgeInsets.symmetric(vertical: 4.0, horizontal: 12.0),
decoration: const BoxDecoration(
color: Colors.white,
border: Border(bottom: BorderSide(color: Colors.grey)),
),
child: ListTile(
onTap: () => print(""),
title: Text(event.title),
),
);
},
),
);
}
}
}
这是因为当您在地图中添加事件时,所选日期值为:(2023-08-30 00:00:00.000)
当您点击某一天时,它会给出:(2023-08-30 00:00:00.000Z)
只需更新您的 onDaySelected:
onDaySelected: (selectedDay, focusedDay) {
setState(() {
_selectedDay = DateTime.parse(
DateFormat('yyyy-MM-dd HH:mm:ss.SSS').format(selectedDay));
});
},