You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter技术问题:如何在MapEntry内实现多层groupBy分组

Solution for Multi-Level Grouping in Flutter ListView

Got it, let's get that two-level grouping working for your ListView. The core idea is to nest the groupBy calls—first group your data by continent, then within each continent group, group again by the located field. We'll also handle the null value for located so it shows up neatly in the UI.

Modified Full Code

import 'package:collection/collection.dart';
import 'package:flutter/material.dart';

class ListModel {
  String country;
  String located;
  String continent;
  ListModel({this.country, this.continent, this.located});
}

void main() => runApp(MaterialApp(home: MyApp()));

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var data = [
      ListModel(country: 'United States', continent: 'North American', located: 'center'),
      ListModel(country: 'Mexico', continent: 'North American', located: 'southern'),
      ListModel(country: 'Guatemala', continent: 'North American', located: 'southern'),
      ListModel(country: 'Australia', continent: 'Australia', located: null),
    ];

    // First group by continent, then group each continent's list by located (handle null with fallback)
    final groupedData = groupBy<ListModel, String>(data, (e) => e.continent)
        .map((continent, models) => MapEntry(
              continent,
              groupBy<ListModel, String>(models, (e) => e.located ?? 'Unspecified'),
            ));

    // Convert to list of continent entries for ListView
    final continentEntries = groupedData.entries.toList();

    return Scaffold(
      appBar: AppBar(title: const Text('Multi-Level Grouped List')),
      body: ListView.builder(
        itemCount: continentEntries.length,
        itemBuilder: (BuildContext context, int index) {
          final continentEntry = continentEntries[index];
          final continentName = continentEntry.key;
          final locatedGroups = continentEntry.value.entries.toList();

          return Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              // Continent header
              Container(
                width: double.infinity,
                color: Colors.grey[700],
                padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
                child: Text(
                  continentName,
                  style: const TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold),
                ),
              ),
              // Iterate through each located group in the continent
              ...locatedGroups.map((locatedEntry) {
                final locatedName = locatedEntry.key;
                final countries = locatedEntry.value;

                return Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    // Located group header
                    Container(
                      width: double.infinity,
                      color: Colors.grey[300],
                      padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 24),
                      child: Text(
                        locatedName,
                        style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
                      ),
                    ),
                    // List of countries in this located group
                    ...countries.map((countryModel) {
                      return Padding(
                        padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 32),
                        child: Text(countryModel.country),
                      );
                    }).toList(),
                  ],
                );
              }).toList(),
            ],
          );
        },
      ),
    );
  }
}

Key Changes Explained

  • Nested Grouping: We first group the data by continent, then for each continent's list of ListModel, we group again by located. The e.located ?? 'Unspecified' ensures entries with null for located are grouped under a readable label instead of showing null in the UI.
  • Visual Hierarchy: We updated the widget tree to clearly separate levels:
    1. Dark grey header for each continent (stands out as the top-level group).
    2. Light grey header for each located subgroup (distinct but not overpowering).
    3. Indented country names under their respective located groups for clear visual flow.
  • Cleaner Widget Construction: Used the spread operator (...) to flatten widget lists, avoiding messy nested Column structures and making the code easier to read.

This will give you the exact grouped display you want:

  • North American
    • center
      • United States
    • southern
      • Mexico
      • Guatemala
  • Australia
    • Unspecified
      • Australia

内容的提问来源于stack exchange,提问作者Kel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 09:37:27