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

Flutter开发:如何实现含动态数据的嵌套列表UI布局

Flutter实现嵌套动态列表的UI方案与数据集成

一、可用的核心Widget

  • ListView.builder:外层和内层都采用这个Widget,因为数据是动态可变的,builder模式能按需渲染列表项,提升性能,避免一次性加载所有元素。
  • ExpansionTile:作为外层列表的每个项,自带展开/收起交互,完美适配“词性分类-展开显示释义”的需求,还能自定义头部标题样式。
  • Card:给外层的ExpansionTile包裹一层Card,让每个分类项拥有独立的卡片样式,和示例UI的视觉效果匹配。
  • Container/Row/Column:用来排版内层的释义和例句,调整间距、文字样式,让内容布局更清晰易读。

二、完整代码实现(含JSON数据集成)

1. 定义数据实体类

先把JSON数据转换成Dart实体类,方便数据管理与类型安全:

// 释义模型
class Meaning {
  final String description;
  final String example;

  Meaning({required this.description, required this.example});

  // 从Map转换为实体对象
  factory Meaning.fromMap(Map<String, dynamic> map) {
    return Meaning(
      description: map['description'],
      example: map['example'],
    );
  }
}

// 词性分类模型
class WordCategory {
  final String type;
  final List<Meaning> meanings;

  WordCategory({required this.type, required this.meanings});

  // 从Map转换为实体对象
  factory WordCategory.fromMap(Map<String, dynamic> map) {
    return WordCategory(
      type: map['type'],
      meanings: (map['meaning'] as List).map((m) => Meaning.fromMap(m)).toList(),
    );
  }
}

2. 集成示例JSON数据

将你提供的JSON数据转换成Dart可直接使用的列表:

List<WordCategory> getMockData() {
  final rawData = [
    {
      'type': 'adjective',
      'meaning': [
        {'description': 'description 1', 'example': 'example 1'},
        {'description': 'description 2', 'example': 'example 2'},
        {'description': 'description 3', 'example': 'example 3'},
        {'description': 'description 4', 'example': 'example 4'},
      ]
    },
    {
      'type': 'noun',
      'meaning': [
        {'description': 'description 1', 'example': 'example 1'},
        {'description': 'description 2', 'example': 'example 2'},
      ]
    },
    {
      'type': 'verb',
      'meaning': [
        {'description': 'description 1', 'example': 'example 1'},
      ]
    },
    {
      'type': 'adverb',
      'meaning': [
        {'description': 'description 1', 'example': 'example 1'},
        {'description': 'description 2', 'example': 'example 2'},
        {'description': 'description 3', 'example': 'example 3'},
      ]
    }
  ];

  return rawData.map((item) => WordCategory.fromMap(item)).toList();
}

3. 页面UI完整实现

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Nested List Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const NestedListPage(),
    );
  }
}

class NestedListPage extends StatelessWidget {
  const NestedListPage({super.key});

  @override
  Widget build(BuildContext context) {
    final categories = getMockData();

    return Scaffold(
      appBar: AppBar(title: const Text('词性释义列表')),
      body: ListView.builder(
        padding: const EdgeInsets.symmetric(vertical: 8),
        itemCount: categories.length,
        itemBuilder: (context, index) {
          final category = categories[index];
          return Card(
            margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
            child: ExpansionTile(
              title: Text(
                category.type.toUpperCase(),
                style: const TextStyle(fontWeight: FontWeight.bold),
              ),
              children: [
                ListView.builder(
                  shrinkWrap: true, // 让内层列表自适应内容高度
                  physics: const NeverScrollableScrollPhysics(), // 禁用内层滚动,交由外层统一控制
                  itemCount: category.meanings.length,
                  itemBuilder: (context, meaningIndex) {
                    final meaning = category.meanings[meaningIndex];
                    return Padding(
                      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            '释义:${meaning.description}',
                            style: const TextStyle(fontSize: 16),
                          ),
                          const SizedBox(height: 6),
                          Text(
                            '例句:${meaning.example}',
                            style: TextStyle(fontSize: 14, color: Colors.grey[600]),
                          ),
                          if (meaningIndex != category.meanings.length - 1)
                            const Divider(height: 24),
                        ],
                      ),
                    );
                  },
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}

// 此处粘贴前面定义的Meaning、WordCategory类和getMockData函数

代码说明

  • 外层通过ListView.builder加载所有词性分类,每个分类用Card+ExpansionTile组合,实现可展开的卡片效果。
  • 内层用ListView.builder加载对应分类的释义和例句,通过shrinkWrap: true让内层列表自适应内容高度,避免布局溢出;禁用内层滚动后,整个页面的滚动体验更统一。
  • 数据部分通过实体类解析,无论后续JSON数据的数量如何变化,都能自动适配渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 17:40:03