0

在过去的几天里,我一直在为正确的未来建造者定位而苦苦挣扎。我使用 syncfusion_calendar 包来显示来自我的 API 的 json 数据,每次用户更改日历月份时,我都会向 API 调用一个新的请求。问题是用户没有被告知正在进行的数据下载,我很乐意通过在加载时显示 CircularProgressIndicator 而不是日历来做到这一点。

我的 pubspec 文件以防万一:

name: flutter_viaapp_startmenu
description: A new Flutter application.

# The following line prevents the package from being accidentally published to
# pub.dev using `pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev

# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+1

environment:
  sdk: ">=2.7.0 <3.0.0"

dependencies:
  firebase_core: ^0.5.0+1
  cloud_firestore: ^0.14.4
  firebase_messaging: ^7.0.3
  firebase_in_app_messaging: 0.2.3
  webview_flutter: ^1.0.7
  flutter_staggered_grid_view: ^0.3.3
  easy_localization: ^2.3.2
  intl: ^0.16.1
  http: ^0.12.2
  syncfusion_flutter_calendar: ^18.3.51
  shared_preferences: ^0.5.12
  flutter_local_notifications: ^3.0.3

  flutter_localizations:
    sdk: flutter
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.0

dev_dependencies:
  flutter_test:
    sdk: flutter

# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

# The following section is specific to Flutter.
flutter:
  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  assets:
    - assets/menu.jpg
    - assets/welcome.jpg
    - assets/translations/en.json
    - assets/translations/lv.json

  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.dev/assets-and-images/#resolution-aware.

  # For details regarding adding assets from package dependencies, see
  # https://flutter.dev/assets-and-images/#from-packages

  # To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  # example:
  # fonts:
  #   - family: Schyler
  #     fonts:
  #       - asset: fonts/Schyler-Regular.ttf
  #       - asset: fonts/Schyler-Italic.ttf
  #         style: italic
  #   - family: Trajan Pro
  #     fonts:
  #       - asset: fonts/TrajanPro.ttf
  #       - asset: fonts/TrajanPro_Bold.ttf
  #         weight: 700
  #
  # For details regarding fonts from package dependencies,
  # see https://flutter.dev/custom-fonts/#from-packages

我的主要日历文件:

import 'dart:async';
import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:syncfusion_flutter_calendar/calendar.dart';
import 'package:intl/intl.dart';

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

  @override
  State<StatefulWidget> createState() => _MyLecturesGraphState();
}

class _MyLecturesGraphState extends State<Lecture_graph> {
  Future<List<Lecture>> _future;
  List<Lecture> lectures;
  DateTime _selectedDate = new DateTime.now();
  List<LectureTime> _times;

  //TODO make this empty after SO post
  var coursecode = "IT3";

  @override
  void initState() {
    _selectedDate = new DateTime(
        _selectedDate.year,
        _selectedDate.month,
        15,
        _selectedDate.hour,
        _selectedDate.minute,
        _selectedDate.second,
        _selectedDate.millisecond,
        _selectedDate.microsecond);
    _future = downloadData();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(coursecode + " | Lectures"),
          actions: [
            LecturesNavigationControls(),
          ],
        ),
        body: lectureGraphList());
  }

  Future<String> _checkSavedCourse() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();

    String _coursecode = prefs.getString('savedCourse');

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

  Widget lectureGraphList() {
    return FutureBuilder<List<Lecture>>(
      future: _future,
      builder: (BuildContext context, AsyncSnapshot<List<Lecture>> snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Center(
            child: SizedBox(
              child: const Expanded(
                  child: Center(child: const CircularProgressIndicator())),
              width: 100,
              height: 100,
            ),
          );
        } else {
          if (snapshot.hasError)
            return Center(child: Text('Error: ${snapshot.error}'));
          else
            return showLectures(lectures);
        }
      },
    );
  }


//THIS FUNCTION IS CALLED EVERY TIME TO DOWNLOAD NEW DATA FROM API

  Future<List<Lecture>> downloadData() async {
    //get saved course
    if (coursecode == "" || coursecode == null) {
      coursecode = await _checkSavedCourse();
      //debug
      print('courscode recieved from sharedprefs');
    }

    //if there is no date selected, select today
    if (_selectedDate == null) _selectedDate = new DateTime.now();

    //build request URL
    var requestURL =
        'https://lekcijas.va.lv/lekcijas_android/getMonthLectures.php?date=' +
            DateFormat('yyyy-MM').format(_selectedDate) +
            "&breaks&program=" +
            coursecode;
    //wait for response
    var response = await http.get(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)));
      _getDataSource(lectures);
    } catch (e) {
      print(e.toString());
    }

    return Future.value(lectures);
  }

  Widget showLectures(List<Lecture> lectures) {
    return Card(
      child: Row(
        children: [
          Expanded(
              child: SfCalendar(
                  view: CalendarView.month,
                  firstDayOfWeek: 1,
                  onViewChanged: (ViewChangedDetails details) {
                    if (_selectedDate.month != details.visibleDates[15].month) {
                      WidgetsBinding.instance.addPostFrameCallback((_) {
                        _selectedDate = details.visibleDates[15];


                          setState(() {



//CALENDAR MONTH CHANGE IS CALLED HERE 



                              downloadData();
                

        });
                      });
                    }
                  },
                  dataSource: LectureTimeDataSource(_times),
                  monthViewSettings: MonthViewSettings(
                      appointmentDisplayMode:
                          MonthAppointmentDisplayMode.indicator,
                      showAgenda: true,
                      agendaStyle: AgendaStyle(
                          appointmentTextStyle:
                              TextStyle(color: Colors.black))),
                  showNavigationArrow: true))
        ],
      ),
    );
  }

  void _getDataSource(List<Lecture> lectures) {
    var lectureTimes = <LectureTime>[];
    lectures.forEach((element) {
      lectureTimes.add(LectureTime(
          (element.classroom + "  " + element.lecture),
          DateTime.parse(element.datums + " " + element.start),
          DateTime.parse(element.datums + " " + element.end),
          hexToColor(element.color),
          false));
    });

    setState(() {
      _times = lectureTimes;
    });
  }
}

class LecturesNavigationControls extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        IconButton(
          //TODO find normal icon
          icon: const Icon(Icons.wheelchair_pickup),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => CourseSelectionPage()),
            );
          },
        ),
      ],
    );
  }
}

class LectureTimeDataSource extends CalendarDataSource {
  LectureTimeDataSource(List<LectureTime> source) {
    appointments = source;
  }

  @override
  DateTime getStartTime(int index) {
    return appointments[index].from;
  }

  @override
  DateTime getEndTime(int index) {
    return appointments[index].to;
  }

  @override
  String getSubject(int index) {
    return appointments[index].eventName;
  }

  @override
  Color getColor(int index) {
    return appointments[index].background;
  }

  @override
  bool isAllDay(int index) {
    return appointments[index].isAllDay;
  }
}

class LectureTime {
  LectureTime(
      this.eventName, this.from, this.to, this.background, this.isAllDay);

  String eventName;
  DateTime from;
  DateTime to;
  Color background;
  bool isAllDay;
}

Color hexToColor(String code) {
  return new Color(int.parse(code.substring(1, 7), radix: 16) + 0xFF000000);
}


class Lecture{
  final String programs;
  final String lecture;
  final String lecturer;
  final String start;
  final String end;
  final String classroom;
  final String color;
  final String datums;

  Lecture({this.programs, this.lecture, this.lecturer, this.start, this.end, this.classroom, this.color, this.datums});

  factory Lecture.fromJson(Map<String, dynamic> json) {
    return Lecture(
      programs: json['nodala'] as String,
      lecture: json['kurss'] as String,
      lecturer : json['lektors'] as String,
      start: json['sakums'] as String,
      end: json['beigas'] as String,
      classroom: json['nosaukums'] as String,
      color: json['iela'] as String,
      datums: json['datums'] as String,
    );
  }
}


class LectureTime {
  LectureTime(
      this.eventName, this.from, this.to, this.background, this.isAllDay);

  String eventName;
  DateTime from;
  DateTime to;
  Color background;
  bool isAllDay;
}

请使用“IT3”字符串作为 API 的课程代码。API 请求 url 示例在这里

4

2 回答 2

0

您可以添加一个名为 loadingData 的变量,并将其默认设置为 false。然后,在调用 downloadData() 之前将其设置为 true,当函数完成时,将其设置回 false。最后,在 build 方法里面: child: loadingData ? CircularProgressIndicator() : SfCalendar(...)

于 2021-01-27T03:04:25.950 回答
0

Based on the provided information and code snippet, we have checked, and your requirement is “<strong>Showing the CircularProgressIndicator when loading calendar”. We have prepared a simple sample for loading circular progress indicator with loading online data to the calendar. Please find the sample from the following link,

Sample link: https://www.syncfusion.com/downloads/support/directtrac/312448/ze/minimum_appointmentduration298839661.zip

Also, we have a KB document for loading the online data to Flutter calendar with a simple loading text message. In the same way, you will use CircularProgressIndicator.

KB link: https://www.syncfusion.com/kb/11568/how-to-load-the-json-data-online-to-the-flutter-event-calendar-sfcalendar-appointments

We hope that the above sample and KB helps you. Please let us know if you need further assistance.

于 2021-01-27T08:53:54.077 回答