我正在将table_calendar插件添加到我的flutter应用程序中。到目前为止,多亏了我从你们那里得到的帮助,大多数事情都在运行。
这是我得到的下一个问题。当我点击日历上的日期时,我得到以下错误,然后什么也没有发生。
======== Exception caught by gesture ===============================================================
The following _TypeError was thrown while handling a gesture:
type '_MapStream<QuerySnapshot<Map<String, dynamic>>, List<Event>>' is not a subtype of type 'Map<DateTime, List<dynamic>>'
When the exception was thrown, this was the stack:
#0 _AppointmentCalendarScreenState._onDaySelected.<anonymous closure> (package:tonnah/screens/appointment_calendar.dart:73:29)
下面是第73行的代码
void _onDaySelected(DateTime day, List events, List holidays) {
_eventsStream = _firestoreService.getEventStream(day);
setState(() {
_streamController.add(_eventsStream); <<<<< LINE 73
//_selectedEvents = _eventsStream;
});
}
下面是我填充_eventsStream的位置:
_eventsStream = _firestoreService.getEventStream(_selectedDay);
Stream<List<Event>> getEventStream(DateTime dateTime) {
return _db.collection('agency').doc(globals.agencyId).collection('event')
.where('eventDate', isGreaterThanOrEqualTo: Timestamp.fromDate(dateTime))
.snapshots().map((snapshot) => snapshot.docs
.map((document) => Event.fromFirestore(document.data()))
.toList());
}
它还用于将事件指示器放在日历上:
StreamBuilder(
//stream: _firestoreService.getEventStream(_selectedDay),
stream: _db.collection('agency').doc(globals.agencyId).collection('event')
.where('eventDate', isGreaterThanOrEqualTo: Timestamp.fromDate(_selectedDay))
.snapshots().map((snapshot) => snapshot.docs
.map((document) => Event.fromFirestore(document.data()))
.toList()),
builder: (context, snapshot) {
if (snapshot.hasData) {
List<Event> snapData;
//return snapData = snapshot.data;
_eventsStream = snapshot.data;
_eventsMap = convertToMap(_eventsStream);
//_selectedEventsMap = _eventsMap[_selectedDay] ?? [];
return _buildTableCalendar();
} else {
return CircularProgressIndicator();
}
},
),
我知道存在类型差异,但我如何使它们匹配?
以下是日历页面中的代码:
// Example holidays
final Map<DateTime, List> _holidays = {
DateTime(2020, 1, 1): ['New Year\'s Day'],
DateTime(2020, 1, 6): ['Epiphany'],
DateTime(2020, 2, 14): ['Valentine\'s Day'],
DateTime(2020, 4, 21): ['Easter Sunday'],
DateTime(2020, 4, 22): ['Easter Monday'],
};
//final eventsRef = FirebaseFirestore.instance.collection('agency').doc(globals.agencyId).collection('event');
final _firestoreService = FirestoreService();
bool showSpinner = false;
var _eventsStream;
var _eventsMap;
final _selectedDay = DateTime.now();
class AppointmentCalendarScreen extends StatefulWidget {
AppointmentCalendarScreen({Key key, this.title}) : super(key: key);
final String title;
@override
_AppointmentCalendarScreenState createState() => _AppointmentCalendarScreenState();
}
class _AppointmentCalendarScreenState extends State<AppointmentCalendarScreen> with TickerProviderStateMixin {
//var _eventsList;
//Map<DateTime, List> _selectedEventsMap;
AnimationController _animationController;
CalendarController _calendarController;
StreamController<Map<DateTime, List>> _streamController;
@override
void initState() {
super.initState();
_streamController = StreamController();
_eventsStream = _firestoreService.getEventStream(_selectedDay);
_calendarController = CalendarController();
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 400),
);
_animationController.forward();
}
@override
void dispose() {
_animationController.dispose();
_calendarController.dispose();
_streamController.close();
super.dispose();
}
void _onDaySelected(DateTime day, List events, List holidays) {
_eventsStream = _firestoreService.getEventStream(day);
setState(() {
_streamController.add(_eventsStream);
//_selectedEvents = _eventsStream;
});
}
void _onVisibleDaysChanged(DateTime first, DateTime last,
CalendarFormat format) {
}
void _onCalendarCreated(DateTime first, DateTime last,
CalendarFormat format) {
}
@override
Widget build(BuildContext context) {
final eventProvider = Provider.of<EventProvider>(context);
FirebaseFirestore _db = FirebaseFirestore.instance;
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('assets/images/Appbar_logo.png',
fit: BoxFit.cover, height: 56),
],
),
),
backgroundColor: Colors.white,
resizeToAvoidBottomInset: false,
body: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
StreamBuilder(
stream: _firestoreService.getEventStream(_selectedDay),
builder: (context, snapshot) {
if (snapshot.hasData) {
List<Event> snapData;
_eventsStream = snapshot.data;
_eventsMap = convertToMap(_eventsStream);
//_selectedEventsMap = _eventsMap[_selectedDay] ?? [];
return _buildTableCalendar();
} else {
return CircularProgressIndicator();
}
},
),
const SizedBox(height: 8.0),
//_buildButtons(),
ElevatedButton(
onPressed: () async {
setState(() {
showSpinner = true;
});
try {
globals.newAgency = true;
//eventProvider.saveEvent();
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => AddEventScreen()));
setState(() {
showSpinner = false;
});
} catch (e) {
// todo: add better error handling
print(e);
}
},
child: Text('Add Event'),
),
const SizedBox(height: 8.0),
Expanded(child: _buildEventList()),
],
),
);
}
// Simple TableCalendar configuration (using Styles)
Widget _buildTableCalendar() {
return TableCalendar(
calendarController: _calendarController,
locale: 'en_US',
events: _eventsMap,
holidays: _holidays,
startingDayOfWeek: StartingDayOfWeek.sunday,
calendarStyle: CalendarStyle(
selectedColor: Colors.deepOrange[400],
todayColor: Colors.deepOrange[200],
markersColor: Colors.deepPurpleAccent,
outsideDaysVisible: false,
),
headerStyle: HeaderStyle(
formatButtonTextStyle:
TextStyle().copyWith(color: Colors.white, fontSize: 15.0),
formatButtonDecoration: BoxDecoration(
color: Colors.deepOrange[400],
borderRadius: BorderRadius.circular(16.0),
),
),
onDaySelected: _onDaySelected,
onVisibleDaysChanged: _onVisibleDaysChanged,
onCalendarCreated: _onCalendarCreated,
);
}
Widget _buildHolidaysMarker() {
return Icon(
Icons.add_box,
size: 20.0,
color: Colors.blueGrey[800],
);
}
Widget _buildEventList() {
final _db = FirebaseFirestore.instance;
return Container(
child: StreamBuilder<QuerySnapshot>(
//stream: FirestoreService().getEvent(),
stream: _db.collection('agency').doc(globals.agencyId).collection(
'event').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: const Text(
'Loading...',
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
));
} else {
var doc = snapshot.data.docs;
return new ListView.builder(
itemCount: doc.length,
itemBuilder: (BuildContext context, int index) {
Event _event = Event.fromFirestore(
doc[index].data());
return ListTile(
isThreeLine: true,
title: Text(
'${_event.eventName ?? 'n/a'}',
style: TextStyle(
fontWeight: FontWeight.w900,
color: Colors.blueAccent),
),
subtitle: Text.rich(TextSpan(
text:
//'${_event.eventName ?? 'n/a'}, '
'${_event.eventStartTime ?? 'n/a'}, '
'Duration: ${_event.eventDuration ?? 'n/a'}',
children: <TextSpan>[
TextSpan(
text:
'\n${_event.eventDescription ?? 'n/a'}',
style: TextStyle(
fontWeight: FontWeight.w900,
color: Colors.blueGrey),
)
])),
//trailing: Text('MLS#: ${_event.mlsNumber ?? 'n/a'}'),
onTap: () {
globals.newTrxn = false;
/*
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
AddEventScreen(
doc[index].data())));
*/
},
);
}
);
}
},
),
);
}
Map<DateTime, List> convertToMap(List<Event> item) {
Map<DateTime, List> result;
for (int i = 0; i < item.length; i++) {
Event data = item[i];
//get the date and convert it to a DateTime variable
//DateTime currentDate = DateFormat('MM-dd-yyyy - kk:mm').format(data.eventDate);
DateTime currentDate = DateTime(data.eventDate.year, data.eventDate.month, data.eventDate.day, data.eventDate.hour, data.eventDate.minute);
List eventNames = [];
//add the event name to the the eventNames list for the current date.
//search for another event with the same date and populate the eventNames List.
for (int j = 0; j < item.length; j++) {
//create temp calendarItemData object.
Event temp = item[j];
//establish that the temp date is equal to the current date
if (data.eventDate == temp.eventDate) {
//add the event name to the event List.
eventNames.add(temp.eventName);
} //else continue
}
//add the date and the event to the map if the date is not contained in the map
if (result == null) {
result = {
currentDate: eventNames
};
} else {
result[currentDate] = eventNames;
}
return result;
}
}
}
发布于 2021-06-19 09:33:38
你必须转换类型: Map。
创建将在“Map”上转换“_MapStream>,List>”的方法
在你的情况下:转换在'Map>
实际上,您需要以下三种方法:
首先:我上面提到的转换方法。方法示例如下
final int _currentYearInt = DateTime.now().year;
final int _currentMonthInt =
int.parse(addZeroToNumberLowerThanTen(number: DateTime.now().month));
documentsList.forEach((doc) {
Map<DateTime, List<Shift>> _schedule = {};
// "days" is a properties with values: {"10" : [], "12": []}, where "10" is day of month"
doc['days'].forEach((k, v) {
int _shiftDay = int.parse(k);
if (calendarWithMarkedDates[
DateTime.utc(_currentYearInt, _currentMonthInt, _shiftDay)] ==
null) {
calendarWithMarkedDates[
DateTime.utc(_currentYearInt, _currentMonthInt, _shiftDay)] = [];
}
calendarWithMarkedDates[DateTime.utc(_currentYearInt, _currentMonthInt, _shiftDay)]!
.add( "your item. Can be object, map or what you want" );
});
});
第二:"calendarWithMarkedDates“是一个LinkedHashMap,它保存所有标记的日期。F.e.来自服务器的响应日期: 1.07、5.07、12.07。转换为LinkedHashMap之后的所有日期都存储在这个"calendarWithMarkedDates“中。
final calendarWithMarkedDates = LinkedHashMap<DateTime, List<Shift>>(
equals: isSameDay,
hashCode: getHashCode,
);
第三:"currentScheduleForDay“它是yu必须调用的函数,就像TableCalendar中没有参数的属性"eventLoader”的值一样。
这意味着:
currentScheduleForDay的好方法
错误的方法: currentScheduleForDay()
List<Shift> currentScheduleForDay(DateTime day) {
return currentCalendarWithMarkedDates[day] ?? [];
}
当使用currentScheduleForDay方法(不带"()")时,TableCalendar by它自己循环遍历月份中的所有日期,并使用inovke方法遍历所有日期。
https://stackoverflow.com/questions/68041383
复制相似问题