Flutter中如何在ListView内根据地址数量动态生成卡片盒子
实现思路
你当前的代码中地址、经纬度、图片资源都是硬编码的,要适配服务端动态返回的数据,按下面几个步骤调整即可:
1. 改造Centres实体类
你现在的Centres类是用静态常量写死的,首先要改成可承载服务端返回数据的结构,除了地址外还要包含卡片需要用到的图片链接、纬度、经度等字段:
class Centre { final String address; final double lat; final double lng; final String imageUrl; // 后续需要其他字段(比如评分、营业时间)也可以直接在这里补充 Centre({ required this.address, required this.lat, required this.lng, required this.imageUrl, }); // 新增fromJson方法,方便将服务端返回的json数据直接转成实体对象 factory Centre.fromJson(Map<String, dynamic> json) { return Centre( address: json['address'] as String, lat: json['lat'] as double, lng: json['lng'] as double, imageUrl: json['image_url'] as String, ); } }
2. 在页面State中新增数据状态和请求逻辑
你的Map页面是StatefulWidget,直接在状态类里添加变量存储返回的点位数据,同时补充加载、错误状态,页面初始化的时候调用接口拉取服务端数据:
class _MapState extends State<Map> { // 原有代码保持不变,新增以下变量 List<Centre> centreList = []; bool isLoading = true; String? errorMsg; @override void initState() { super.initState(); // 页面初始化时触发服务端数据拉取 fetchCentresFromServer(); } // 服务端数据请求方法 Future<void> fetchCentresFromServer() async { try { // 这里替换为你自己封装的json_service中的实际接口请求方法 final response = await yourApiRequestMethod(); // 将接口返回的json数组转成Centre实体列表 List<Centre> list = (response as List).map((item) => Centre.fromJson(item)).toList(); setState(() { centreList = list; isLoading = false; }); } catch (e) { setState(() { errorMsg = e.toString(); isLoading = false; }); } } // 原有代码保持不变...
3. 将硬编码的横向ListView改为动态构建
你现在_buildContainer方法里手动写了3个卡片,替换为ListView.builder动态生成即可,有多少条服务端返回的数据就会自动生成多少个卡片,同时补充加载、错误状态的适配:
// 注意要把_buildContainer方法移动到_MapState类内部,否则无法访问centreList状态数据 Widget _buildContainer() { if (isLoading) { return const Align( alignment: Alignment.bottomLeft, child: Padding( padding: EdgeInsets.all(20.0), child: CircularProgressIndicator(), ), ); } if (errorMsg != null) { return Align( alignment: Alignment.bottomLeft, child: Padding( padding: const EdgeInsets.all(20.0), child: Text('加载失败:$errorMsg'), ), ); } return Align( alignment: Alignment.bottomLeft, child: Container( margin: const EdgeInsets.symmetric(vertical: 20.0), height: 150.0, child: ListView.builder( scrollDirection: Axis.horizontal, itemCount: centreList.length, // 卡片数量和服务端返回的点位数量完全一致 itemBuilder: (context, index) { final centre = centreList[index]; return Padding( padding: const EdgeInsets.symmetric(horizontal: 10.0), child: _boxes( centre.imageUrl, centre.lat, centre.lng, centre.address, ), ); }, ), ), ); }
注意事项
- 原来定义的
_buildContainer、_boxes、myDetailsContainer1都是顶层函数,需要移动到_MapState类内部,或者把centreList作为参数传递,否则无法访问状态数据 - 服务端返回的字段名要和Centre类fromJson方法里的key对应,如果字段名不一致自己调整对应关系即可
- 如果需要实现点击卡片跳转到地图对应点位的功能,直接在
_boxes的onTap回调里调用地图控制器的animateCamera方法,传入对应centre的经纬度参数即可
内容的提问来源于stack exchange,提问作者artistAhmed
相关产品推荐
相关产品推荐

