flutter 将事件添加到table_calendar

zdwk9cvp  于 2022-12-14  发布在  Flutter
关注(0)|答案(1)|浏览(222)

我是flutter/Dart编程的新手,对下面的代码感到困惑。我没有写代码,但我想用它来显示table_calendar插件的日历网格上的事件标记。

class calEvent {
  final String title;

  const calEvent(this.title);

  @override
  String toString() => title;
}

/// Example events.
///
/// Using a [LinkedHashMap] is highly recommended if you decide to use a map.
final kEvents = LinkedHashMap<DateTime, List<calEvent>>(
  equals: isSameDay,
  hashCode: getHashCode,
)..addAll(_kEventSource);
**<<<<<<  I think FirestoreService().getEvent() would go here but I don't know how to add it or convert from Stream<List<Event>> to LinkedHashMap<DateTime, List<calEvent>>  >>>>>>**
final _kEventSource = Map.fromIterable(List.generate(50, (index) => index),
    key: (item) => DateTime.utc(2020, 10, item * 5),
    value: (item) => List.generate(
        item % 4 + 1, (index) => calEvent('Event $item | ${index + 1}')))
  ..addAll({
    DateTime.now(): [
      calEvent('Today\'s Event 1'),
      calEvent('Today\'s Event 2'),
    ],
  });

int getHashCode(DateTime key) {
  return key.day * 1000000 + key.month * 10000 + key.year;
}

/// Returns a list of [DateTime] objects from [first] to [last], inclusive.
List<DateTime> daysInRange(DateTime first, DateTime last) {
  final dayCount = last.difference(first).inDays + 1;
  return List.generate(
    dayCount,
        (index) => DateTime.utc(first.year, first.month, first.day + index),
  );
}

final kNow = DateTime.now();
final kFirstDay = DateTime(kNow.year, kNow.month - 3, kNow.day);
final kLastDay = DateTime(kNow.year, kNow.month + 3, kNow.day);

我在另一个页面上创建了事件,并将它们存储在Firebase集合中。我可以将这些事件从集合中拉入Stream〈DateTime,List〉,但我希望根据它们应该发生的日期将它们显示在table_calendar网格中。这段代码很好地完成了这一点,但不是从Firebase集合中。我希望在代码中实现它,但使用从Firebase集合中拉事件的代码作为源代码。
我的问题是我不知道如何/在哪里把我的代码放在_kEventSource代码中。我附加了一个包含我的一些代码的文件,这样你就可以看到我在做什么。
我将非常感谢关于这方面的建议。
下面是构建table_calendar的代码:
这是构建基本日历框架并在日历网格下构建事件列表的代码。

class _AppointmentCalendarScreenState extends State<AppointmentCalendarScreen> with TickerProviderStateMixin {
  late final ValueNotifier<List<calEvent>> _selectedEvents;
  late StreamController<Map<DateTime, List>> _streamController;
  CalendarFormat _calendarFormat = CalendarFormat.month;
  RangeSelectionMode _rangeSelectionMode = RangeSelectionMode
      .toggledOff; // Can be toggled on/off by longpressing a date
    
  List<calEvent> _getEventsForDay(DateTime day) {
    // Implementation example
    return kEvents[day] ?? [];
  }

  List<calEvent> _getEventsForRange(DateTime start, DateTime end) {
    // Implementation example
    final days = daysInRange(start, end);

    return [
      for (final d in days) ..._getEventsForDay(d),
    ];
  }

  void _onDaySelected(DateTime selectedDay, DateTime focusedDay) {
    if (!isSameDay(_selectedDay, selectedDay)) {
      setState(() {
        _selectedDay = selectedDay;
        _focusedDay = focusedDay;
        _rangeStart = null; // Important to clean those
        _rangeEnd = null;
        _rangeSelectionMode = RangeSelectionMode.toggledOff;
      });

      _selectedEvents.value = _getEventsForDay(selectedDay);
    }
  }

  @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( **<<<<  I get the events from Firebase here**
            stream: **_firestoreService.getEventStream(_selectedDay)**,
            builder: (context, AsyncSnapshot <List<Event>> eventsSnapShot) {
              if (eventsSnapShot.hasData) {
                var doc = eventsSnapShot.data!;
                for (int i = 0; i < doc.length; i++ ) {
                }
                return _buildTableCalendar();
              } else {
                return CircularProgressIndicator();
              }
            },
          ),

          const SizedBox(height: 8.0),

        ],
      ),
    );
  }

   **This is where the calendar grid is built**
  Widget _buildTableCalendar() {
    return TableCalendar(
      firstDay: kFirstDay,
      lastDay: kLastDay,
      focusedDay: _selectedDay,
      selectedDayPredicate: (day) => isSameDay(_selectedDay, day),
      locale: 'en_US',
      eventLoader: _getEventsForDay, // **This is important**
      //holidays: _holidays,
      
      ),

      onDaySelected: _onDaySelected,
      //onVisibleDaysChanged: _onVisibleDaysChanged,
      //onCalendarCreated: _onCalendarCreated,
      
    );
  }

下面是调用FirestoreService().getEvent()的代码,我使用它从Firebase集合中获取事件:

Stream<List<Event>> getEventStream(DateTime dateTime) async* {
    yield* _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());
  }

这是事件数据模型:

class Event {
  final String? eventName;
  //final TimeOfDay eventStartTime;
  final DateTime? eventStartTime;
  final String? eventDuration;
  final DateTime? eventDate;
  final String? eventDescription;
  final String? agentId;
  final String? agencyId;

  Event(
      {this.eventName,
      this.eventStartTime,
      this.eventDuration,
      this.eventDate,
      this.eventDescription,
      this.agentId,
      this.agencyId});

  Map<String, dynamic> toMap() {
    return {
      'eventName': eventName,
      'eventStartTime': eventStartTime,
      'eventDuration': eventDuration,
      'eventDate': eventDate,
      'eventDescription': eventDescription,
      'agentId': agentId,
      'agencyId': agencyId,
    };
  }

  // pass in a map and get an object back
  Event.fromFirestore(Map<String, dynamic> firestore)
      : eventName = firestore['eventName'],
        eventStartTime = firestore['eventStartTime'].toDate(),
        eventDuration = firestore['eventDuration'],
        eventDate = firestore['eventDate'].toDate(),
        eventDescription = firestore['eventDescription'],
        agentId = firestore['agentId'],
        agencyId = firestore['agencyId'];
}
e4yzc0pl

e4yzc0pl1#

kEvents之前,你必须再做一个map
以下是使用代码片段的步骤。

  • 从firebase获取数据(List<Event>

你已经在做了。
我们将其命名为snapshot.data

  • 将这些事件Map到kEventSource
Map<DateTime, List<Event>> kEventSource = {};

    (snapshot.data).forEach((element) {
      kEventSource[DateTime(  
        element.time.year,
        element.time.month,
        element.time.day,
      )] = kEventSource[DateTime(
                element.time.year,
                element.time.month,
                element.time.day,
              )] !=
              null
          ? [
              ...kEventSource[DateTime(
                element.time.year,
                element.time.month,
                element.time.day,
              )],
              element
            ]
          : [element];
    });

现在我们有了一个map数据结构,其中dateTime作为键,当天的事件列表作为值。
示例:

{
  "2 July 2021" : [Event1, Event2, ...],
  ...
}
  • 现在定义了kEvents
final kEvents = LinkedHashMap<DateTime, List<Event>>(
      equals: isSameDay,
      hashCode: getHashCode,
    )..addAll(kEventSource);

isSameDay函数来自软件包本身。
源代码:

/// Checks if two DateTime objects are the same day.
/// Returns `false` if either of them is null.
bool isSameDay(DateTime? a, DateTime? b) {
  if (a == null || b == null) {
    return false;
  }

  return a.year == b.year && a.month == b.month && a.day == b.day;
}

对于getHashCode也是如此。不过您可以修改它。
源代码:

int getHashCode(DateTime key) {
    return key.day * 1000000 + key.month * 10000 + key.year;
  }

现在您有了KEvents,因此可以使用其他功能,如在范围内选择等。
参考编号:table_calender
我鼓励您查看软件包作者提供的示例。

相关问题