如何实现选择日期范围调用API过滤后展示Flutter DataTable的页面
完全可以实现该需求,以下是完整的实现方案和可运行示例代码:

1. 前置依赖准备
首先在pubspec.yaml中添加所需依赖:
dependencies: flutter: sdk: flutter http: ^1.1.0 # 用于API网络请求 intl: ^0.18.1 # 用于日期格式化
修改完成后执行flutter pub get安装依赖。
2. 完整实现代码
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; import 'package:intl/intl.dart'; class DateRangeFilterPage extends StatefulWidget { const DateRangeFilterPage({super.key}); @override State<DateRangeFilterPage> createState() => _DateRangeFilterPageState(); } class _DateRangeFilterPageState extends State<DateRangeFilterPage> { DateTime? _startDate; DateTime? _endDate; List<Map<String, dynamic>> _tableData = []; bool _isLoading = false; final DateFormat _dateFormat = DateFormat('yyyy-MM-dd'); // 调出系统自带的日期范围选择器 Future<void> _pickDateRange() async { final pickedRange = await showDateRange( context: context, firstDate: DateTime(2020), lastDate: DateTime.now(), initialDateRange: _startDate != null && _endDate != null ? DateTimeRange(start: _startDate!, end: _endDate!) : null, ); if (pickedRange != null) { setState(() { _startDate = pickedRange.start; _endDate = pickedRange.end; }); } } // 点击搜索按钮调用API获取过滤后的数据 Future<void> _searchData() async { if (_startDate == null || _endDate == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('请先选择日期范围')), ); return; } setState(() { _isLoading = true; _tableData.clear(); }); try { // 替换为你的实际API地址,请求参数名根据后端约定调整 final response = await http.get( Uri.parse('https://your-api-domain.com/query/data').replace(queryParameters: { 'startDate': _dateFormat.format(_startDate!), 'endDate': _dateFormat.format(_endDate!), }), ); if (response.statusCode == 200) { final res = json.decode(response.body); // 假设接口返回的列表数据在result字段下,根据实际返回结构调整 setState(() { _tableData = List<Map<String, dynamic>>.from(res['result']); }); } } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('数据请求失败:${e.toString()}')), ); } finally { setState(() { _isLoading = false; }); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('数据查询')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 顶部日期选择+搜索按钮区域 Row( children: [ Expanded( child: InkWell( onTap: _pickDateRange, child: InputDecorator( decoration: const InputDecoration( labelText: '日期范围', border: OutlineInputBorder(), suffixIcon: Icon(Icons.date_range), ), child: Text( _startDate == null || _endDate == null ? '请选择起止日期' : '${_dateFormat.format(_startDate!)} 至 ${_dateFormat.format(_endDate!)}', ), ), ), ), const SizedBox(width: 16), ElevatedButton( onPressed: _searchData, style: ElevatedButton.styleFrom(padding: const EdgeInsets.all(16)), child: const Text('搜索'), ), ], ), const SizedBox(height: 20), // 底部表格展示区域 Expanded( child: _isLoading ? const Center(child: CircularProgressIndicator()) : _tableData.isEmpty ? const Center(child: Text('暂无匹配数据')) : SingleChildScrollView( scrollDirection: Axis.horizontal, child: DataTable( border: TableBorder.all(color: Colors.grey.shade300), columnSpacing: 40, // 表头根据你的业务字段调整即可 columns: const [ DataColumn(label: Text('序号')), DataColumn(label: Text('商品名称')), DataColumn(label: Text('交易日期')), DataColumn(label: Text('交易金额')), DataColumn(label: Text('交易状态')), ], // 把接口数据映射为表格行 rows: _tableData.map((item) { return DataRow(cells: [ DataCell(Text(item['id'].toString())), DataCell(Text(item['goodsName'])), DataCell(Text(item['tradeDate'])), DataCell(Text(item['tradeAmount'].toString())), DataCell(Text(item['tradeStatus'])), ]); }).toList(), ), ), ), ], ), ), ); } }
自定义调整说明
- 可以修改
showDateRange的firstDate和lastDate参数限制可选的日期范围 - 替换代码中的API地址、请求参数名、返回数据解析逻辑为你实际的后端接口规则
- 修改
DataTable的columns配置和rows的映射逻辑,匹配你的业务字段即可 - 如果需要支持分页、排序等表格功能,直接在
DataTable基础上扩展即可
内容的提问来源于stack exchange,提问作者Kevin Valencia Cruz
相关产品推荐
相关产品推荐

