【问题标题】:Flutter table_calendar load todayFlutter table_calendar 今天加载
【发布时间】:2021-03-16 16:32:07
【问题描述】:

我在我的项目中使用table_calendar 包,但到目前为止我遇到了两个问题:

  1. 日历不会在日历下方加载今天的事件,我很想听听一些关于如何完成这一任务的想法。
  2. 即使我将(下面的代码)放入表格参数中,它也不允许切换日历模式。

为我的问题的第二个要点切换日历模式的代码:

availableCalendarFormats: const {
              CalendarFormat.month: '',
              CalendarFormat.week: '',
            },

以防万一,这里是有问题的页面的整个代码:

class Lecture_graph extends StatefulWidget {
  Lecture_graph({Key key}) : super(key: key);

  @override
  State<Lecture_graph> createState() => myLectureGraph();
}

class myLectureGraph extends State<Lecture_graph>
    with TickerProviderStateMixin {
  List _selectedEvents;
  DateTime _selectedDate = DateTime.now();
  Map<DateTime, List<Lecture>> _events;
  CalendarController _calendarController;
  AnimationController _animationController;
  List<Lecture> _lectures;
  String coursecode = "";
  bool isJoin, isBreaks = false;
  bool isLoading = true;

  final Map<DateTime, List> _holidays = {
    // DateTime(2021, 1, 1): ['New Year\'s Day'],
    // DateTime(2021, 2, 14): ['Valentine\'s Day'],
    // DateTime(2021, 3, 8): ['Woman\'s Day'],
  };

  Future<Map<DateTime, List>> getLectures(DateTime _selectedDate) async {
    print("getLectures started.");
    setState(() {
      isLoading = true;
    });

    Map<DateTime, List<Lecture>> mapFetch = {};

    //get saved course
    if (coursecode == "" || coursecode == null) {
      coursecode = await _checkSavedCourse();
      //debug
      print('courscode recieved from sharedprefs');
    }

    //build request URL
    var requestURL =
        'https://lekcijas.va.lv/lekcijas_android/getMonthLectures.php?date=' +
            DateFormat('yyyy-MM').format(_selectedDate) +
            (isBreaks ? "&breaks" : "") +
            (isJoin ? "&join" : "") +
            "&program=" +
            coursecode +
            "&lang=" +
            AppLocalizations.of(context).translate('request_language');
    print("Lecture request url : $requestURL");
    //wait for response
    var response = await http.get(Uri.parse(requestURL));
    var data = json.decode(response.body)["result"];

    //clear array after each request
    if (_lectures != null) _lectures.clear();

    try {
      //create lectures from json response
      _lectures = List<Lecture>.from(data.map((x) => Lecture.fromJson(x)));
    } on Exception catch (_) {
      print("Error occured getting lectures");
    }

    _lectures.forEach((element) {
      if (mapFetch[element.lecture_date] != null) {
        mapFetch[element.lecture_date] += [element];
      } else {
        mapFetch[element.lecture_date] = [element];
      }
    });

    setState(() {
      isLoading = false;
    });

    print("getLectures finished.");
    return mapFetch;
  }

  Future<void> _saveVales(String key, bool value) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    print("Sharedpref $key is set to $value now");
    prefs.setBool(key, value);
  }

  Future<void> _checkSavedParameters() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    isBreaks = prefs.getBool('lectures_breaks') == null
        ? false
        : prefs.getBool('lectures_breaks');
    isJoin = prefs.getBool('lectures_join') == null
        ? false
        : prefs.getBool('lectures_join');
  }

  Future<String> _checkSavedCourse() async {
    //check saved parameters for lecture requests too
    await _checkSavedParameters();

    SharedPreferences prefs = await SharedPreferences.getInstance();
    String _coursecode = prefs.getString('savedCourse');

    if (_coursecode == "" || _coursecode == null) {
      Navigator.pop(context);
      Navigator.push(
        context,
        MaterialPageRoute(builder: (context) => CourseSelectionPage()),
      );

      return null;
    } else {
      return _coursecode;
    }
  }

  void _onDaySelected(DateTime day, List events) {
    print('CALLBACK: _onDaySelected');
    setState(() {
      _selectedEvents = events;
    });
  }

  @override
  void initState() {
    super.initState();

    //enable portrait only mode
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
    ]);

    _selectedEvents = [];
    _calendarController = CalendarController();
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 400),
    );

    _animationController.forward();

    WidgetsBinding.instance.addPostFrameCallback((_) {
      getLectures(_selectedDate).then((val) => setState(() {
            _events = val;
          }));
    });
  }

  @override
  void dispose() {
    _calendarController.dispose();

    //unlock orientation mode
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeRight,
      DeviceOrientation.landscapeLeft,
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
    ]);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(coursecode +
            " | " +
            AppLocalizations.of(context).translate('lectures_title')),
        actions: <Widget>[
          IconButton(
            icon: Icon(
              Icons.settings,
              color: Colors.white,
            ),
            onPressed: () {
              showDialog(
                context: context,
                builder: (context) {
                  return StatefulBuilder(
                    builder: (context, setState) {
                      return AlertDialog(
                        title: Text(
                            AppLocalizations.of(context).translate('settings')),
                        content: Column(
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            Row(
                              children: [
                                CupertinoSwitch(
                                  value: isJoin,
                                  onChanged: (bool value) {
                                    _saveVales('lectures_join', value);
                                    isJoin = value;
                                    WidgetsBinding.instance
                                        .addPostFrameCallback((_) {
                                      getLectures(_selectedDate)
                                          .then((val) => setState(() {
                                                _events = val;
                                              }));
                                    });
                                  },
                                ),
                                Text(AppLocalizations.of(context)
                                    .translate('join_lectures'))
                              ],
                            ),
                            SizedBox(height: 10),
                            Row(
                              children: [
                                CupertinoSwitch(
                                  value: isBreaks,
                                  onChanged: (bool value) {
                                    _saveVales('lectures_breaks', value);
                                    isBreaks = value;
                                    WidgetsBinding.instance
                                        .addPostFrameCallback((_) {
                                      getLectures(_selectedDate)
                                          .then((val) => setState(() {
                                                _events = val;
                                              }));
                                    });
                                  },
                                ),
                                Text(AppLocalizations.of(context)
                                    .translate('show_breaks'))
                              ],
                            ),
                            SizedBox(height: 10),
                            SizedBox(
                              width: double.infinity,
                              child: OutlinedButton(
                                  onPressed: () {
                                    //close popup
                                    Navigator.pop(context);
                                    //close page
                                    Navigator.pop(context);
                                    Navigator.push(
                                      context,
                                      MaterialPageRoute(
                                          builder: (context) =>
                                              CourseSelectionPage()),
                                    );
                                  },
                                  child: Text(
                                    AppLocalizations.of(context)
                                        .translate('select_course'),
                                    style: TextStyle(color: Colors.lime),
                                  )),
                            )
                          ],
                        ),
                        actions: <Widget>[
                          FlatButton(
                            onPressed: () => Navigator.pop(context),
                            child: Text(AppLocalizations.of(context)
                                .translate('close')),
                          ),
                        ],
                      );
                    },
                  );
                },
              );
            },
          )
        ],
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            isLoading
                ? Expanded(child: Center(child: CircularProgressIndicator()))
                : _buildTableCalendarWithBuilders(),
            const SizedBox(height: 2.0),
            Expanded(child: _buildEventList()),
          ],
        ),
      ),
    );
  }

  Widget _buildTableCalendarWithBuilders() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Card(
          color: Colors.white,
          margin: const EdgeInsets.all(8.0),
          clipBehavior: Clip.antiAlias,
          child: TableCalendar(
            locale:
                AppLocalizations.of(context).translate('request_language') ==
                        'lv'
                    ? "lv_LV"
                    : "en_US",
            initialSelectedDay: _selectedDate,
            calendarController: _calendarController,
            events: _events,
            holidays: _holidays,
            initialCalendarFormat: CalendarFormat.month,
            formatAnimation: FormatAnimation.scale,
            startingDayOfWeek: StartingDayOfWeek.monday,
            availableGestures: AvailableGestures.all,
            availableCalendarFormats: const {
              CalendarFormat.month: '',
              CalendarFormat.week: '',
            },
            calendarStyle: CalendarStyle(
              outsideDaysVisible: false,
              weekendStyle: TextStyle().copyWith(color: Colors.blue[800]),
              holidayStyle: TextStyle().copyWith(color: Colors.blue[800]),
            ),
            daysOfWeekStyle: DaysOfWeekStyle(
              weekendStyle: TextStyle().copyWith(color: Colors.blue[600]),
            ),
            headerStyle: HeaderStyle(
              centerHeaderTitle: true,
              formatButtonVisible: false,
            ),
            builders: CalendarBuilders(
              selectedDayBuilder: (context, date, _) {
                return FadeTransition(
                  opacity:
                      Tween(begin: 0.0, end: 1.0).animate(_animationController),
                  child: Container(
                    margin: const EdgeInsets.all(4.0),
                    padding: const EdgeInsets.only(top: 5.0, left: 6.0),
                    color: Colors.deepOrange[300],
                    width: 100,
                    height: 100,
                    child: Text(
                      '${date.day}',
                      style: TextStyle().copyWith(fontSize: 16.0),
                    ),
                  ),
                );
              },
              todayDayBuilder: (context, date, _) {
                return Container(
                  margin: const EdgeInsets.all(4.0),
                  padding: const EdgeInsets.only(top: 5.0, left: 6.0),
                  color: Colors.amber[400],
                  width: 100,
                  height: 100,
                  child: Text(
                    '${date.day}',
                    style: TextStyle().copyWith(fontSize: 16.0),
                  ),
                );
              },
              markersBuilder: (context, date, events, holidays) {
                final children = <Widget>[];

                if (events.isNotEmpty) {
                  children.add(
                    Positioned(
                      right: 1,
                      bottom: 1,
                      child: _buildEventsMarker(date, events),
                    ),
                  );
                }

                if (holidays.isNotEmpty) {
                  children.add(
                    Positioned(
                      right: -2,
                      top: -2,
                      child: _buildHolidaysMarker(),
                    ),
                  );
                }

                return children;
              },
            ),
            onDaySelected: (date, events, holidays) {
              _onDaySelected(date, events);
              _animationController.forward(from: 0.0);
            },
            onVisibleDaysChanged: _onVisibleDaysChanged,
          ),
        ),
      ],
    );
  }

  void _onVisibleDaysChanged(
      DateTime first, DateTime last, CalendarFormat format) {
    _selectedDate = first;
    WidgetsBinding.instance.addPostFrameCallback((_) {
      getLectures(_selectedDate).then((val) => setState(() {
            _events = val;
          }));
    });
    print('CALLBACK: _onVisibleDaysChanged');
  }

  Widget _buildEventsMarker(DateTime date, List events) {
    return AnimatedContainer(
      duration: const Duration(milliseconds: 300),
      decoration: BoxDecoration(
        shape: BoxShape.circle,
        color: _calendarController.isSelected(date)
            ? Colors.brown[500]
            : _calendarController.isToday(date)
                ? Colors.brown[300]
                : Colors.green[400],
      ),
      width: 18.0,
      height: 18.0,
      child: Center(
        child: Text(
          '${events.length}',
          style: TextStyle().copyWith(
              color: Colors.white, fontSize: 12.0, fontWeight: FontWeight.w900),
        ),
      ),
    );
  }

  Widget _buildHolidaysMarker() {
    return Icon(
      Icons.add_box,
      size: 20.0,
      color: Colors.blueGrey[800],
    );
  }

  Widget _buildEventList() {
    return ListView(
      children: _selectedEvents.reversed
          .map((lecture) => Container(
                decoration: BoxDecoration(
                  border: Border.all(width: 0.1),
                  // borderRadius: BorderRadius.circular(2.0),
                  color: hexToColor(lecture.color),
                ),
                margin:
                    const EdgeInsets.symmetric(horizontal: 6.0, vertical: 1.5),
                child: ListTile(
                  title: Column(
                    children: [
                      Align(
                        alignment: Alignment.centerLeft,
                        child: Text(
                          lecture.start + " - " + lecture.end,
                          style: new TextStyle(
                            fontSize: 12.0,
                            color: Colors.black,
                          ),
                        ),
                      ),
                      Align(
                        alignment: Alignment.centerLeft,
                        child: Text(lecture.lecture,
                            style: new TextStyle(
                              fontSize: 16.0,
                              color: Colors.black,
                            )),
                      ),
                    ],
                  ),
                  onTap: () => displayDialog(lecture, context),
                ),
              ))
          .toList(),
    );
  }

  void displayDialog(Lecture selectedLecture, BuildContext ctx) {
    //if selected lecture is a break
    if (!selectedLecture.lecturer.isEmpty &&
        !selectedLecture.classroom.isEmpty &&
        !selectedLecture.programs.isEmpty) {
      showDialog(
        barrierDismissible: true,
        context: ctx,
        builder: (BuildContext context) => new AlertDialog(
          title: new Text(AppLocalizations.of(context).translate('info_title')),
          content: new Wrap(
            runSpacing: 5,
            children: [
              Align(
                alignment: Alignment.centerLeft,
                child: Text(
                    AppLocalizations.of(context).translate('info_time') +
                        selectedLecture.start +
                        " - " +
                        selectedLecture.end),
              ),
              Align(
                alignment: Alignment.centerLeft,
                child: Text(
                    AppLocalizations.of(context).translate('info_lecturer') +
                        selectedLecture.lecturer),
              ),
              Align(
                alignment: Alignment.centerLeft,
                child: Text(
                    AppLocalizations.of(context).translate('info_classroom') +
                        selectedLecture.classroom),
              ),
              Align(
                alignment: Alignment.centerLeft,
                child: Text(
                    AppLocalizations.of(context).translate('info_lecture') +
                        selectedLecture.lecture),
              ),
              Align(
                alignment: Alignment.centerLeft,
                child: Text(
                    AppLocalizations.of(context).translate('info_date') +
                        DateFormat('yyyy-MM-dd')
                            .format(selectedLecture.lecture_date)
                            .toString()),
              ),
              Align(
                alignment: Alignment.centerLeft,
                child: Text(
                    AppLocalizations.of(context).translate('info_programs') +
                        selectedLecture.programs),
              ),
            ],
          ),
          actions: [
            new TextButton(
              child: Text(AppLocalizations.of(context).translate('close')),
              onPressed: () => Navigator.pop(context, true),
            ),
          ],
        ),
      );
    }
  }
}

如果有人想查看 JSON 请求结果,here 就是那个链接。

【问题讨论】:

    标签: flutter


    【解决方案1】:

    所以我解决了这个问题,将它添加到 TableCalendar() 参数中: (一旦日历完成构建,我就调用 selectedEvents 变量更新(因为当我从 http 请求接收数据时,我显示的是 CircularProgressIndicator 而不是它))

    onCalendarCreated: (d1, d2, cf){WidgetsBinding.instance
                    .addPostFrameCallback((_) => _onDaySelected(_selectedDate, _events[_selectedDate]));},
    

    将 _onDaySelected 方法更改为: (这里我将 selectedday 变量更改为从日历单击收到的日期并更改 selectedEvents 的状态,将它们替换为 total_events_map[key_which_is_selectedDay])

    void _onDaySelected(DateTime day, List events) {
        print('CALLBACK: _onDaySelected');
        //dates are used with nulled time
        _selectedDate = DateTime(day.year, day.month, day.day, 0, 0, 0);
        setState(() {
          _selectedEvents = _events[_selectedDate];
        });
      }
    

    并将 _buildEventList() 更改为: (所以如果 selectedEvents 为空,它会告诉用户,如果不是,则从 selectedEvents 生成项目列表)

    Widget _buildEventList() {
        if(_selectedEvents == null)
          return ListView(
            children: [
              Card(
                clipBehavior: Clip.antiAlias,
                margin: const EdgeInsets.all(8.0),
                child: ListTile(
                  title: Column(
                    children: [
                      Align(
                        alignment: Alignment.centerLeft,
                        child: Text(tr('nothing_planned'),
                            style: new TextStyle(
                              fontSize: 16.0,
                              color: Colors.black,
                            )),
                      ),
                    ],
                  ),
                ),
              ),
            ],
          );
        else return ListView(
          children: _selectedEvents.reversed
              .map((lecture) => Container(
                    decoration: BoxDecoration(
                      border: Border.all(width: 0.1),
                      // borderRadius: BorderRadius.circular(2.0),
                      color: hexToColor(lecture.color),
                    ),
                    margin:
                        const EdgeInsets.symmetric(horizontal: 6.0, vertical: 1.5),
                    child: ListTile(
                      title: Column(
                        children: [
                          Align(
                            alignment: Alignment.centerLeft,
                            child: Text(
                              lecture.start + " - " + lecture.end,
                              style: new TextStyle(
                                fontSize: 12.0,
                                color: Colors.black,
                              ),
                            ),
                          ),
                          Align(
                            alignment: Alignment.centerLeft,
                            child: Text(lecture.lecture,
                                style: new TextStyle(
                                  fontSize: 16.0,
                                  color: Colors.black,
                                )),
                          ),
                        ],
                      ),
                      onTap: () => displayDialog(lecture, context),
                    ),
                  ))
              .toList(),
        );
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-23
      • 1970-01-01
      相关资源
      最近更新 更多