dart 如何在flutter中显示嵌套的标题?

4jb9z9bj  于 2023-03-05  发布在  Flutter
关注(0)|答案(1)|浏览(112)

我想显示标题、子标题和记录。我正在获取所有数据,但在显示时出现问题。我尝试了,但未获得输出。我无法将数据分配给特定标题及其子标题。
有人能解释一下我哪里做错了吗

    • JSON响应**
[
    {
        "meetingId": 3214440,
        "venue": "Musselburgh",
        "eventTypeId": 7,
        "countryCode": "GB",
        "races": {
            "1.210613875": {
                "marketName": "Musselburgh 1st Mar - 1m7f Mdn Hrd",
                "marketType": null,
                "eventId": 3214440,
                "eventName": "Musselburgh 1st Mar",
                "startTime": "2023-03-01T13:50:00+00:00"
            }
        }
    },
    {
        "meetingId": 3214445,
        "venue": "Lingfield",
        "eventTypeId": 7,
        "countryCode": "GB",
        "races": {
            "1.210613936": {
                "marketName": "Lingfield 1st Mar - 7f Hcap",
                "marketId": "1.210613936",
                "marketType": null,
                "eventId": 3214445,
                "eventName": "Lingfield 1st Mar",
                "startTime": "2023-03-01T14:00:00+00:00"
            },
            "1.210613943": {
                "marketName": "Lingfield 1st Mar - 6f Hcap",
                "marketId": "1.210613943",
                "marketType": null,
                "eventId": 3214445,
                "eventName": "Lingfield 1st Mar",
                "startTime": "2023-03-01T14:30:00+00:00"
            }
        }
    },
    {
        "meetingId": 32144452,
        "venue": "Wincanton",
        "eventTypeId": 7,
        "countryCode": "GB",
        "races": {
            "1.210614012": {
                "marketName": "Wincanton 1st Mar - 2m5f Nov Hrd",
                "marketId": "1.210614012",
                "marketType": null,
                "eventId": 32144452,
                "eventName": "Wincanton 1st Mar",
                "startTime": "2023-03-01T14:10:00+00:00"
            }
        }
    },
    {
        "meetingId": 3214785,
        "venue": "Philadelphia",
        "eventTypeId": 7,
        "countryCode": "US",
        "races": {
            "1.210679950": {
                "marketName": "Philadelphia (US) 01st Mar - R1 6f Mdn Claim",
                "marketId": "1.210679950",
                "marketType": null,
                "eventId": 3214785,
                "eventName": "Philadelphia (US) 01st Mar",
                "startTime": "2023-03-01T16:55:00+00:00"
            }
        }
    },
    {
        "meetingId": 32147853,
        "venue": "Gulfstream Park",
        "eventTypeId": 7,
        "countryCode": "US",
        "races": {
            "1.210680638": {
                "marketName": "Gulfstream Park (US) 01st Mar - R1 1m1f Mdn Claim",
                "marketId": "1.210680638",
                "marketType": null,
                "eventId": 32147853,
                "eventName": "Gulfstream Park (US) 01st Mar",
                "startTime": "2023-03-01T17:10:00+00:00"
            },
            "1.210680641": {
                "marketName": "Gulfstream Park (US) 01st Mar - R2 1m Mdn Claim",
                "marketId": "1.210680641",
                "marketType": null,
                "eventId": 32147853,
                "eventName": "Gulfstream Park (US) 01st Mar",
                "startTime": "2023-03-01T17:39:00+00:00"
            }
        }
    },
    {
        "meetingId": 3214786,
        "venue": "Tampa Bay Downs",
        "eventTypeId": 7,
        "countryCode": "US",
        "races": {
            "1.210680506": {
                "marketName": "Tampa Bay Downs (US) 01st Mar - R1 6f Claim",
                "marketId": "1.210680506",
                "marketType": null,
                "eventId": 3214786,
                "eventName": "Tampa Bay Downs (US) 01st Mar",
                "startTime": "2023-03-01T17:28:00+00:00"
        }
    },
    {
        "meetingId": 3214508,
        "venue": "Kenilworth",
        "eventTypeId": 7,
        "countryCode": "ZA",
        "races": {
            "1.210632129": {
                "marketName": "Kenilworth (RSA) 1st Mar - R1 1000m Mdn",
                "marketId": "1.210632129",
                "marketType": null,
                "eventId": 3214508,
                "eventName": "Kenilworth (RSA) 1st Mar",
                "startTime": "2023-03-01T10:35:00+00:00"
            }
        }
    }
]
    • 代码**
List<String> cdArray = [];
  List<String> countryCodeArray = [];
  List<CustomRaceMarket> raceArray = [];
  List<Venue> venueArray = [];

final ScrollController scrollController = ScrollController();

@override
  void initState() {
    // TODO: implement initState
    super.initState();
    getHorse();
  }

@override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      body: SizedBox(
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width,
        child: ListView.builder(
          itemCount: countryCodeArray.length,
          controller: scrollController,
          itemBuilder: (BuildContext context, int mainGroupIndex) {
            return StickyHeader(
              header: Text(countryCodeArray[mainGroupIndex]),
              controller: scrollController,
              overlapHeaders: false,
              content: ListView.builder(
                itemCount: venueArray.length,
                primary: false,
                shrinkWrap: true,
                itemBuilder: (BuildContext context, int subGroupIndex) {
                  final list = ListView.builder(
                    itemCount: raceArray.length,
                    primary: false,
                    shrinkWrap: true,
                    itemBuilder: (BuildContext context, int recordIndex) {
                      return Text(raceArray[recordIndex].eventName);
                    },
                  );
                  return MyStickyHeader(
                    header:countryCodeArray[mainGroupIndex] == venueArray[subGroupIndex].countrycode
                        ? Text(venueArray[subGroupIndex].venue)
                        : SizedBox(),
                    controller: scrollController,
                    content: list,
                  );
                },
              ),
            );
          },
        ),
      ),
    );
  }

  void getHorse() async {
    ApiService apiService = ApiService();
    List<Race> lm = await apiService.getTodayHorseRacing(context);
    setState(() {});
    for (var element in lm) {
      cdArray.add(element.countryCode);
      var obj = Venue(venue: element.venue, countrycode: element.countryCode);
      if (element.countryCode == "GB") {
       venueArray.add(obj);
      }
      if (element.countryCode == "AU") {
         venueArray.add(obj);
      }
      if (element.countryCode == "US") {
         venueArray.add(obj);
      }
      if (element.countryCode == "ZA") {
         venueArray.add(obj);
      }
      for (var element1 in element.races.values) {
        var obj = CustomRaceMarket(
            marketName: element1.marketName,
            marketId: element1.marketId,
            eventId: element1.eventId,
            eventName: element1.eventName,
            startTime: element1.startTime,
            open: element1.open,
            inplay: element1.inplay,
            port: element1.port,
            venue: element.venue,
            countryCode: element.countryCode);
        if (element.meetingId == element1.eventId) {
          raceArray.add(obj);
        }
      }
    }

    countryCodeArray = cdArray.toSet().toList();

  }
}

class Venue {
  final String venue;
  final String countrycode;

  Venue({required this.venue, required this.countrycode});
}
    • 我的输出**
    • 预期产出**

有没有我做错了什么,请有人能帮助我与此作为Flutter是新的我

7gcisfzg

7gcisfzg1#

使用Model类会使工作更容易一些。你可以有一个国家模型,一个会议模型和一个比赛模型。我将省略那些对所示UI不必要的字段。

class Race {
  Race({required this.startTime});

  final DateTime startTime;

  factory Race.fromMap(Map<String, dynamic> map) {
    return Race(
      startTime: DateTime.parse(map['startTime']),
    );
  }
}

class Meeting {
  Meeting({required this.venue, required this.races});

  final String venue;
  final Map<String, Race> races;

  Map<String, dynamic> toMap() {
    return <String, dynamic>{
      'venue': venue,
      'races': races,
    };
  }

  factory Meeting.fromMap(Map<String, dynamic> map) {
    return Meeting(
      venue: map['venue'] as String,
      races: (map['races'] as Map<String, Map<String, dynamic>>).map(
        (key, value) => MapEntry(key, Race.fromMap(value)),
      ),
    );
  }
}

class Country {
  final String countryCode;
  final List<Meeting> meetings;

  Country({
    required this.countryCode,
    required this.meetings,
  });

  Country copyWith({
    String? countryCode,
    List<Meeting>? meetings,
  }) {
    return Country(
      countryCode: countryCode ?? this.countryCode,
      meetings: meetings ?? this.meetings,
    );
  }

  factory Country.fromMap(Map<String, dynamic> map) {
    return Country(
      countryCode: map['countryCode'],
      meetings: (map['meetings'] as List<Map<String, dynamic>>)
          .map((e) => Meeting.fromMap(e))
          .toList(),
    );
  }
}

您将能够从jsonResponse获得国家/地区列表。

List<Country> fetchCountries() {
  final countries = <Country>[];
  String currentCountryCode = '';
  for (final meetingJson in jsonResponse) {
    final countryCode = meetingJson['countryCode'] as String;
    if (countryCode != currentCountryCode) {
      currentCountryCode = countryCode;
      countries.add(
        Country(
          countryCode: countryCode,
          meetings: [],
        ),
      );
    }
    final meeting = Meeting.fromMap(meetingJson);
    countries.last = countries.last.copyWith(
      meetings: [...countries.last.meetings, meeting],
    );
  }
  return countries;
}

我不太确定你使用了哪个包来获取stickyHeader,所以这里有一个相当简单的UI实现,没有它,头文件的行为略有不同。它们一个堆叠在另一个的顶部。然而,切换到包应该足够容易。

Widget build(BuildContext context) {
  final countries = fetchCountries();
  final primaryColor = Theme.of(context).primaryColor;

  return Scaffold(
    body: CustomScrollView(
      slivers: [
        for (final country in countries) ...[
          SliverAppBar(
            pinned: true,
            centerTitle: false,
            title: Text(country.countryCode),
          ),
          SliverList(
            delegate: SliverChildListDelegate(
              [
                for (final meeting in country.meetings)
                  Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          meeting.venue,
                          style: TextStyle(
                            fontWeight: FontWeight.bold,
                            color: primaryColor,
                          ),
                        ),
                        const SizedBox(height: 8),
                        Wrap(
                          spacing: 8,
                          runSpacing: 8,
                          children: meeting.races.values.map(
                            (race) {
                              final startDate = race.startTime;
                              final startDateHour =
                                  startDate.hour.toString().padLeft(2, '0');
                              final startDateMinute =
                                  startDate.minute.toString().padLeft(2, '0');
                              final formattedDate =
                                '$startDateHour:$startDateMinute';
                              return Container(
                                padding: const EdgeInsets.all(16),
                                decoration: BoxDecoration(
                                  border: Border.all(color: primaryColor),
                                ),
                                child: Text(formattedDate),
                              );
                            },
                          ).toList(),
                        ),
                      ],
                    ),
                  ),
              ],
            ),
          ),
        ],
      ],
    ),
  );
}

关键是我们有三个循环:一个循环遍历所有国家获取国家代码,一个内循环遍历所有会议获取地点,第三个嵌套循环遍历会议中的所有比赛。使用模型有助于确保我们在访问属性时具有类型安全。

相关问题