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

Flutter如何从导入CSV生成的隐藏表格中读取单元格值赋值给自定义组件

实现方案

第一步:调整CSV数据加载逻辑

你之前写的RouteNameTable组件仅用于加载CSV且渲染隐藏表格,逻辑冗余,我们可以直接将CSV加载逻辑调整为输出路由数据列表,无需渲染隐藏表格。
首先确认你的CSV结构固定为如下格式即可适配(如果CSV第一行为表头后续可以直接跳过):

routeNumberrouteNamerouteColor
33Corstorphine - Caversham - City - Wakari0xFFF067A6
.........

第二步:实现数据加载+渲染组件

直接新建一个路由列表组件,加载完CSV后直接生成RouteTemplate列表:

import 'package:flutter/material.dart';
import 'package:csv/csv.dart';
import 'package:flutter/services.dart' show rootBundle;

class RouteTemplateList extends StatefulWidget {
  const RouteTemplateList({Key? key}) : super(key: key);

  @override
  State<RouteTemplateList> createState() => _RouteTemplateListState();
}

class _RouteTemplateListState extends State<RouteTemplateList> {
  List<List<dynamic>> _csvData = [];
  bool _isLoading = true;

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

  // 加载CSV数据
  Future<void> _loadCsvData() async {
    final csvString = await rootBundle.loadString("assets/routes.csv");
    final csvTable = const CsvToListConverter().convert(csvString);
    setState(() {
      _csvData = csvTable;
      _isLoading = false;
    });
  }

  // 兼容多种格式的色值转Color方法
  Color _parseColor(String colorStr) {
    // 处理带#前缀的色值
    if (colorStr.startsWith('#')) {
      colorStr = colorStr.replaceFirst('#', '0xFF');
    } 
    // 处理不带0x前缀的十六进制色值
    else if (!colorStr.startsWith('0x')) {
      colorStr = '0xFF$colorStr';
    }
    return Color(int.parse(colorStr));
  }

  @override
  Widget build(BuildContext context) {
    if (_isLoading) {
      // 加载中状态可自定义为其他占位UI
      return const CircularProgressIndicator();
    }
    // 如果CSV没有表头,删除.skip(1)即可从第一行开始读取数据
    return Column(
      children: _csvData.skip(1).map((row) {
        return RouteTemplate(
          routeNumber: row[0].toString(),
          routeName: row[1].toString(),
          routeColor: _parseColor(row[2].toString()),
        );
      }).toList(),
    );
  }
}

第三步:多场景复用优化

如果需要在应用多处使用该CSV数据,可将加载逻辑抽为全局工具类,缓存加载完成的数据避免重复读取Assets:

class CsvRouteLoader {
  static List<List<dynamic>>? _routeData;

  static Future<List<List<dynamic>>> loadRouteData() async {
    if (_routeData != null) return _routeData!;
    final csvString = await rootBundle.loadString("assets/routes.csv");
    _routeData = const CsvToListConverter().convert(csvString);
    return _routeData!;
  }
}

之后任意位置调用CsvRouteLoader.loadRouteData()即可获取已缓存的CSV数据。

注意事项

  • 确保pubspec.yaml中已经正确注册assets/routes.csv资源
  • 可根据实际CSV列顺序调整row[0]、row[1]、row[2]的索引
  • 后续CSV更新后只需替换Assets目录下的文件,无需修改代码即可自动同步数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 22:48:03